@mideind/netskrafl-react 1.9.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/css/netskrafl.css +104 -34
- package/dist/cjs/index.js +2677 -520
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/css/netskrafl.css +104 -34
- package/dist/esm/index.js +2677 -520
- package/dist/esm/index.js.map +1 -1
- package/package.json +2 -1
package/dist/cjs/index.js
CHANGED
|
@@ -27511,6 +27511,54 @@ const requestMoves = (state, options) => {
|
|
|
27511
27511
|
});
|
|
27512
27512
|
};
|
|
27513
27513
|
|
|
27514
|
+
/*
|
|
27515
|
+
|
|
27516
|
+
Types.ts
|
|
27517
|
+
|
|
27518
|
+
Common type definitions for the Explo/Netskrafl user interface
|
|
27519
|
+
|
|
27520
|
+
Copyright (C) 2025 Miðeind ehf.
|
|
27521
|
+
Author: Vilhjalmur Thorsteinsson
|
|
27522
|
+
|
|
27523
|
+
The Creative Commons Attribution-NonCommercial 4.0
|
|
27524
|
+
International Public License (CC-BY-NC 4.0) applies to this software.
|
|
27525
|
+
For further information, see https://github.com/mideind/Netskrafl
|
|
27526
|
+
|
|
27527
|
+
*/
|
|
27528
|
+
// Global constants
|
|
27529
|
+
const RACK_SIZE = 7;
|
|
27530
|
+
const ROWIDS = 'ABCDEFGHIJKLMNO';
|
|
27531
|
+
const BOARD_SIZE = ROWIDS.length;
|
|
27532
|
+
const EXTRA_WIDE_LETTERS = 'q';
|
|
27533
|
+
const WIDE_LETTERS = 'zxmæ';
|
|
27534
|
+
const ZOOM_FACTOR = 1.5;
|
|
27535
|
+
const GATA_DAGSINS_MIN_DATE = '2025-11-01';
|
|
27536
|
+
const ERROR_MESSAGES = {
|
|
27537
|
+
// Translations are found in /static/assets/messages.json
|
|
27538
|
+
1: 'Enginn stafur lagður niður',
|
|
27539
|
+
2: 'Fyrsta orð verður að liggja um byrjunarreitinn',
|
|
27540
|
+
3: 'Orð verður að vera samfellt á borðinu',
|
|
27541
|
+
4: 'Orð verður að tengjast orði sem fyrir er',
|
|
27542
|
+
5: 'Reitur þegar upptekinn',
|
|
27543
|
+
6: 'Ekki má vera eyða í orði',
|
|
27544
|
+
7: 'word_not_found',
|
|
27545
|
+
8: 'word_not_found',
|
|
27546
|
+
9: 'Of margir stafir lagðir niður',
|
|
27547
|
+
10: 'Stafur er ekki í rekkanum',
|
|
27548
|
+
11: 'Of fáir stafir eftir, skipting ekki leyfð',
|
|
27549
|
+
12: 'Of mörgum stöfum skipt',
|
|
27550
|
+
13: 'Leik vantar á borðið - notið F5/Refresh',
|
|
27551
|
+
14: 'Notandi ekki innskráður - notið F5/Refresh',
|
|
27552
|
+
15: 'Rangur eða óþekktur notandi',
|
|
27553
|
+
16: 'Viðureign finnst ekki',
|
|
27554
|
+
17: 'Viðureign er ekki utan tímamarka',
|
|
27555
|
+
18: 'Netþjónn gat ekki tekið við leiknum - reyndu aftur',
|
|
27556
|
+
19: 'Véfenging er ekki möguleg í þessari viðureign',
|
|
27557
|
+
20: 'Síðasti leikur er ekki véfengjanlegur',
|
|
27558
|
+
21: 'Aðeins véfenging eða pass leyfileg',
|
|
27559
|
+
server: 'Netþjónn gat ekki tekið við leiknum - reyndu aftur',
|
|
27560
|
+
};
|
|
27561
|
+
|
|
27514
27562
|
/*
|
|
27515
27563
|
|
|
27516
27564
|
Audio.ts
|
|
@@ -27638,52 +27686,2073 @@ function getAudioManager(state, soundUrls) {
|
|
|
27638
27686
|
return audioManager;
|
|
27639
27687
|
}
|
|
27640
27688
|
|
|
27689
|
+
var Leikir = {
|
|
27690
|
+
en: "Moves",
|
|
27691
|
+
nb: "Trekk",
|
|
27692
|
+
nn: "Trekk",
|
|
27693
|
+
pl: "Ruchy",
|
|
27694
|
+
ga: "Bogann"
|
|
27695
|
+
};
|
|
27696
|
+
var submit_move = {
|
|
27697
|
+
is: "Leika",
|
|
27698
|
+
en: "Move",
|
|
27699
|
+
nb: "Trekk",
|
|
27700
|
+
nn: "Trekk",
|
|
27701
|
+
pl: "Wykonaj ruch",
|
|
27702
|
+
ga: "Bog"
|
|
27703
|
+
};
|
|
27704
|
+
var Spjall = {
|
|
27705
|
+
en: "Chat",
|
|
27706
|
+
nb: "Chat",
|
|
27707
|
+
nn: "Chat",
|
|
27708
|
+
pl: "Czat",
|
|
27709
|
+
ga: "Comhrá"
|
|
27710
|
+
};
|
|
27711
|
+
var player_info = {
|
|
27712
|
+
is: "Upplýsingar um leikmann",
|
|
27713
|
+
en: "Player information",
|
|
27714
|
+
nb: "Spillerinformasjon",
|
|
27715
|
+
nn: "Spelarinformasjon",
|
|
27716
|
+
pl: "Informacje o graczu",
|
|
27717
|
+
ga: "Eolas Imreoir"
|
|
27718
|
+
};
|
|
27719
|
+
var explain_email = {
|
|
27720
|
+
is: "Ef póstfang er gefið upp mun Netskrafl geta sent tölvupóst þegar þú átt leik",
|
|
27721
|
+
en: "If given, Explo can send e-mail to the address when it's your turn in a game",
|
|
27722
|
+
nb: "Hvis oppgitt, kan Explo sende e-post til adressen når det er din tur i et spill",
|
|
27723
|
+
nn: "Viss oppgjeve, kan Explo sende e-post til adressa når det er din tur i eit spel",
|
|
27724
|
+
pl: "Jeśli podano, Explo może wysłać e-mail na ten adres, gdy nadejdzie Twoja kolej w grze",
|
|
27725
|
+
ga: "Más tugadh é, is féidir le Explo ríomhphost a sheoladh chuig an seoladh nuair atá sé do sheal sa chluiche"
|
|
27726
|
+
};
|
|
27727
|
+
var explain_sound = {
|
|
27728
|
+
is: "Stillir hvort hljóðmerki heyrast t.d. þegar andstæðingur leikur og þegar sigur vinnst",
|
|
27729
|
+
en: "Controls whether sounds are played, e.g. when an opponent makes a move or when you win",
|
|
27730
|
+
nb: "Kontrollerer om lyder spilles, f.eks. når en motstander gjør et trekk eller når du vinner",
|
|
27731
|
+
nn: "Kontrollerer om lydar blir spelte, t.d. når ein motstandar gjer eit trekk eller når du vinn",
|
|
27732
|
+
pl: "Kontroluje, czy dźwięki są odtwarzane, np. gdy przeciwnik wykonuje ruch lub gdy wygrywasz",
|
|
27733
|
+
ga: "Rialaíonn sé an seinntear fuaimeanna, m.sh. nuair a bhogann freasúra nó nuair a bhuaigh tú"
|
|
27734
|
+
};
|
|
27735
|
+
var Vista = {
|
|
27736
|
+
en: "Save",
|
|
27737
|
+
nb: "Lagre",
|
|
27738
|
+
nn: "Lagre",
|
|
27739
|
+
pl: "Zapisz",
|
|
27740
|
+
ga: "Sábháil"
|
|
27741
|
+
};
|
|
27742
|
+
var no_helpers = {
|
|
27743
|
+
is: "Með því að velja þessa merkingu lýsir þú því yfir að þú\nskraflir við aðra leikmenn ",
|
|
27744
|
+
en: "By selecting this option, you declare that you play\nagainst other humans ",
|
|
27745
|
+
nb: "Ved å velge dette alternativet, erklærer du at du spiller\nmot andre mennesker ",
|
|
27746
|
+
nn: "Ved å velje dette, stadfester du at du spelar\nmot andre menneske ",
|
|
27747
|
+
pl: "Wybierając tę opcję, deklarujesz, że grasz\nprzeciwko innym ludziom ",
|
|
27748
|
+
ga: "Trí an rogha seo a roghnú, dearbhaíonn tú go n-imríonn tú\ni gcoinne daoine eile "
|
|
27749
|
+
};
|
|
27750
|
+
var Ferill = {
|
|
27751
|
+
en: "History",
|
|
27752
|
+
nb: "Historikk",
|
|
27753
|
+
nn: "Historikk",
|
|
27754
|
+
pl: "Historia",
|
|
27755
|
+
ga: "Stair"
|
|
27756
|
+
};
|
|
27757
|
+
var opp_move = {
|
|
27758
|
+
is: "{opponent} á leik",
|
|
27759
|
+
en: "{opponent}'s turn",
|
|
27760
|
+
nb: "{opponent}s tur",
|
|
27761
|
+
nn: "{opponent} sin tur",
|
|
27762
|
+
pl: "Tura {opponent}",
|
|
27763
|
+
ga: "Seal {opponent}"
|
|
27764
|
+
};
|
|
27765
|
+
var Framvinda = {
|
|
27766
|
+
en: "Progress",
|
|
27767
|
+
nb: "Fremgang",
|
|
27768
|
+
nn: "Framgang",
|
|
27769
|
+
pl: "Postęp",
|
|
27770
|
+
ga: "Dul chun cinn"
|
|
27771
|
+
};
|
|
27772
|
+
var Keppnishamur = {
|
|
27773
|
+
en: "Pro mode",
|
|
27774
|
+
nb: "Pro-modus",
|
|
27775
|
+
nn: "Pro-modus",
|
|
27776
|
+
pl: "Tryb Pro",
|
|
27777
|
+
ga: "Modh Pro"
|
|
27778
|
+
};
|
|
27779
|
+
var with_clock = {
|
|
27780
|
+
is: "Með klukku, 2 x {duration} mínútur",
|
|
27781
|
+
en: "With clock, 2 x {duration} minutes",
|
|
27782
|
+
nb: "Med klokke, 2 x {duration} minutter",
|
|
27783
|
+
nn: "Med klokke, 2 x {duration} minutt",
|
|
27784
|
+
pl: "Z zegarem, 2 x {duration} minut",
|
|
27785
|
+
ga: "Le clog, 2 x {duration} nóiméad"
|
|
27786
|
+
};
|
|
27787
|
+
var Hafna = {
|
|
27788
|
+
en: "Decline",
|
|
27789
|
+
nb: "Avslå",
|
|
27790
|
+
nn: "Avslå",
|
|
27791
|
+
pl: "Odrzuć",
|
|
27792
|
+
ga: "Diúltaigh"
|
|
27793
|
+
};
|
|
27794
|
+
var Afturkalla = {
|
|
27795
|
+
en: "Retract",
|
|
27796
|
+
nb: "Trekk tilbake",
|
|
27797
|
+
nn: "Trekk tilbake",
|
|
27798
|
+
pl: "Wycofaj",
|
|
27799
|
+
ga: "Tarraing siar"
|
|
27800
|
+
};
|
|
27801
|
+
var Hvernig = {
|
|
27802
|
+
en: "How",
|
|
27803
|
+
nb: "Hvordan",
|
|
27804
|
+
nn: "Korleis",
|
|
27805
|
+
pl: "Jak",
|
|
27806
|
+
ga: "Conas"
|
|
27807
|
+
};
|
|
27808
|
+
var Sigur = {
|
|
27809
|
+
en: "Win",
|
|
27810
|
+
nb: "Seier",
|
|
27811
|
+
nn: "Siger",
|
|
27812
|
+
pl: "Zwycięstwo",
|
|
27813
|
+
ga: "Bua"
|
|
27814
|
+
};
|
|
27815
|
+
var Jafntefli = {
|
|
27816
|
+
en: "Draw",
|
|
27817
|
+
nb: "Uavgjort",
|
|
27818
|
+
nn: "Uavgjort",
|
|
27819
|
+
pl: "Remis",
|
|
27820
|
+
ga: "Tarraingt"
|
|
27821
|
+
};
|
|
27822
|
+
var Tap = {
|
|
27823
|
+
en: "Loss",
|
|
27824
|
+
nb: "Tap",
|
|
27825
|
+
nn: "Tap",
|
|
27826
|
+
pl: "Porażka",
|
|
27827
|
+
ga: "Caill"
|
|
27828
|
+
};
|
|
27829
|
+
var Elo = {
|
|
27830
|
+
is: "Elo",
|
|
27831
|
+
en: "Elo",
|
|
27832
|
+
nb: "Elo",
|
|
27833
|
+
nn: "Elo",
|
|
27834
|
+
pl: "Elo",
|
|
27835
|
+
ga: "Elo"
|
|
27836
|
+
};
|
|
27837
|
+
var Lengd = {
|
|
27838
|
+
en: "Duration",
|
|
27839
|
+
nb: "Varighet",
|
|
27840
|
+
nn: "Varigheit",
|
|
27841
|
+
pl: "Czas trwania",
|
|
27842
|
+
ga: "Fad"
|
|
27843
|
+
};
|
|
27844
|
+
var Einkenni = {
|
|
27845
|
+
en: "Identifier",
|
|
27846
|
+
nb: "Identifikator",
|
|
27847
|
+
nn: "Identifikator",
|
|
27848
|
+
pl: "Identyfikator",
|
|
27849
|
+
ga: "Aitheantóir"
|
|
27850
|
+
};
|
|
27851
|
+
var stafur = {
|
|
27852
|
+
en: "letter",
|
|
27853
|
+
nb: "bokstav",
|
|
27854
|
+
nn: "bokstav",
|
|
27855
|
+
pl: "litera",
|
|
27856
|
+
ga: "litir"
|
|
27857
|
+
};
|
|
27858
|
+
var Senda = {
|
|
27859
|
+
en: "Send",
|
|
27860
|
+
nb: "Send",
|
|
27861
|
+
nn: "Send",
|
|
27862
|
+
pl: "Wyślij",
|
|
27863
|
+
ga: "Seol"
|
|
27864
|
+
};
|
|
27865
|
+
var Pass = {
|
|
27866
|
+
en: "Pass",
|
|
27867
|
+
nb: "Pass",
|
|
27868
|
+
nn: "Pass",
|
|
27869
|
+
pl: "Pas",
|
|
27870
|
+
ga: "Pas"
|
|
27871
|
+
};
|
|
27872
|
+
var letter = {
|
|
27873
|
+
is: "staf",
|
|
27874
|
+
en: "letter",
|
|
27875
|
+
nb: "bokstav",
|
|
27876
|
+
nn: "bokstav",
|
|
27877
|
+
pl: "litera",
|
|
27878
|
+
ga: "litir"
|
|
27879
|
+
};
|
|
27880
|
+
var letters = {
|
|
27881
|
+
is: "stafi",
|
|
27882
|
+
en: "letters",
|
|
27883
|
+
nb: "bokstaver",
|
|
27884
|
+
nn: "bokstavar",
|
|
27885
|
+
pl: "litery",
|
|
27886
|
+
ga: "litreacha"
|
|
27887
|
+
};
|
|
27888
|
+
var exchanged = {
|
|
27889
|
+
is: "Skipti um {numtiles} {letters}",
|
|
27890
|
+
en: "Exchanged {numtiles} {letters}",
|
|
27891
|
+
nb: "Byttet ut {numtiles} {letters}",
|
|
27892
|
+
nn: "Bytte ut {numtiles} {letters}",
|
|
27893
|
+
pl: "Wymieniono {numtiles} {letters}",
|
|
27894
|
+
ga: "Mhalartaithe {numtiles} {letters}"
|
|
27895
|
+
};
|
|
27896
|
+
var click_on_game = {
|
|
27897
|
+
is: " - smelltu á viðureign til að skoða stöðuna og leika ef ",
|
|
27898
|
+
en: " - click on a game to view it and make a move if ",
|
|
27899
|
+
nb: " - klikk på et spill for å åpne det og gjøre et trekk hvis ",
|
|
27900
|
+
nn: " - klikk på eit spel for å opne det og gjere eit trekk viss ",
|
|
27901
|
+
pl: " - kliknij na grę, aby ją zobaczyć i wykonać ruch, jeśli ",
|
|
27902
|
+
ga: " - cliceáil ar chluiche chun é a fheiceáil agus bogadh má "
|
|
27903
|
+
};
|
|
27904
|
+
var click_on_challenge = {
|
|
27905
|
+
is: " - smelltu á áskorun til að taka henni og hefja viðureign, eða á ",
|
|
27906
|
+
en: " - click on a challenge to accept it and start a game, or on ",
|
|
27907
|
+
nb: " - klikk på en utfordring for å akseptere den og starte et spill, eller på ",
|
|
27908
|
+
nn: " - klikk på ei utfordring for å akseptere ho og starte eit spel, eller på ",
|
|
27909
|
+
pl: " - kliknij na wyzwanie, aby je zaakceptować i rozpocząć grę, lub na ",
|
|
27910
|
+
ga: " - cliceáil ar dhúshlán chun glacadh leis agus cluiche a thosú, nó ar "
|
|
27911
|
+
};
|
|
27912
|
+
var click_to_review = {
|
|
27913
|
+
is: " - smelltu á viðureign til að skoða hana og rifja upp",
|
|
27914
|
+
en: " - click on a game to review it",
|
|
27915
|
+
nb: " - klikk på et spill for å åpne det og gå gjennom det",
|
|
27916
|
+
nn: " - klikk på eit spel for å opne det og gå gjennom det",
|
|
27917
|
+
pl: " - kliknij na grę, aby ją przejrzeć",
|
|
27918
|
+
ga: " - cliceáil ar chluiche chun athbhreithniú a dhéanamh air"
|
|
27919
|
+
};
|
|
27920
|
+
var Loka = {
|
|
27921
|
+
en: "Close",
|
|
27922
|
+
nb: "Lukk",
|
|
27923
|
+
nn: "Lukk",
|
|
27924
|
+
pl: "Zamknij",
|
|
27925
|
+
ga: "Dún"
|
|
27926
|
+
};
|
|
27927
|
+
var opponent_emptied_rack = {
|
|
27928
|
+
is: "Andstæðingur tæmdi rekkann - þú getur véfengt eða sagt pass",
|
|
27929
|
+
en: "Your opponent emptied the rack - you can challenge or pass",
|
|
27930
|
+
nb: "Motstanderen tømte stativet - du kan utfordre eller passere",
|
|
27931
|
+
nn: "Motstandaren tømde stativet - du kan utfordre eller passere",
|
|
27932
|
+
pl: "Twój przeciwnik opróżnił stojak - możesz rzucić wyzwanie lub spasować",
|
|
27933
|
+
ga: "D'fholmhaigh do chéile comhraic an raca - is féidir leat dúshlán a thabhairt nó pas a fháil"
|
|
27934
|
+
};
|
|
27935
|
+
var Skipta = {
|
|
27936
|
+
en: "Exchange",
|
|
27937
|
+
nb: "Bytte",
|
|
27938
|
+
nn: "Byte",
|
|
27939
|
+
pl: "Wymiana",
|
|
27940
|
+
ga: "Malartú"
|
|
27941
|
+
};
|
|
27942
|
+
var elo_list_choice = {
|
|
27943
|
+
is: "Fólk | Allar | Keppnishamur",
|
|
27944
|
+
en: "Humans | All | Pro mode",
|
|
27945
|
+
nb: "Mennesker | Alle | Pro modus",
|
|
27946
|
+
nn: "Menneske | Alle | Pro-modus",
|
|
27947
|
+
pl: "Ludzie | Wszyscy | Tryb Pro",
|
|
27948
|
+
ga: "Daoine | Gach | Modh Pro"
|
|
27949
|
+
};
|
|
27950
|
+
var stats_choice = {
|
|
27951
|
+
is: "Með þjörkum eða án",
|
|
27952
|
+
en: "With or without robot games",
|
|
27953
|
+
nb: "Med eller uten robotspill",
|
|
27954
|
+
nn: "Med eller utan robotspel",
|
|
27955
|
+
pl: "Z grami robotów lub bez",
|
|
27956
|
+
ga: "Le cluichí róbón nó gan iad"
|
|
27957
|
+
};
|
|
27958
|
+
var Vinningshlutfall = {
|
|
27959
|
+
en: "Winning ratio",
|
|
27960
|
+
nb: "Vinningsforhold",
|
|
27961
|
+
nn: "Vinningsforhold",
|
|
27962
|
+
pl: "Stosunek wygranych",
|
|
27963
|
+
ga: "Cóimheas bua"
|
|
27964
|
+
};
|
|
27965
|
+
var word_not_found = {
|
|
27966
|
+
en: "'{word}' is not in the dictionary",
|
|
27967
|
+
is: "'{word}' finnst ekki í orðasafni",
|
|
27968
|
+
nb: "'{word}' finnes ikke i ordboken",
|
|
27969
|
+
nn: "'{word}' finst ikkje i ordboka",
|
|
27970
|
+
pl: "'{word}' nie znajduje się w słowniku",
|
|
27971
|
+
ga: "Níl '{word}' sa fhoclóir"
|
|
27972
|
+
};
|
|
27973
|
+
var welcome_2 = {
|
|
27974
|
+
is: [
|
|
27975
|
+
"Til auðkenningar tengir Netskrafl tölvupóstfang og nafn við hvern notanda. ",
|
|
27976
|
+
"Að öðru leyti eru ekki geymdar aðrar upplýsingar um notendur ",
|
|
27977
|
+
"en þær sem þeir skrá sjálfir. Annáll er haldinn um umferð um vefinn og um ",
|
|
27978
|
+
"aðgerðir notenda, í því skyni að endurbæta Netskrafl."
|
|
27979
|
+
],
|
|
27980
|
+
en: [
|
|
27981
|
+
"For identification, Explo associates an e-mail address and a name with each user. ",
|
|
27982
|
+
"Apart from this, Explo only stores information which is voluntarily ",
|
|
27983
|
+
"entered by users themselves. A log is kept of web traffic and events within Explo, ",
|
|
27984
|
+
"for the purpose of improving the service."
|
|
27985
|
+
],
|
|
27986
|
+
nb: [
|
|
27987
|
+
"For identifikasjon knytter Explo en e-postadresse og et navn til hver bruker. ",
|
|
27988
|
+
"Utover dette lagrer Explo kun informasjon som frivillig ",
|
|
27989
|
+
"legges inn av brukerne selv. En logg føres over webtrafikk og hendelser innen Explo, ",
|
|
27990
|
+
"i hensikt å forbedre tjenesten."
|
|
27991
|
+
],
|
|
27992
|
+
nn: [
|
|
27993
|
+
"For identifikasjon knyter Explo ei e-postadresse og eit namn til kvar brukar. ",
|
|
27994
|
+
"Utover dette lagrar Explo berre informasjon som frivillig ",
|
|
27995
|
+
"blir lagt inn av brukarane sjølve. Ein logg blir ført over webtrafikk og hendingar innan Explo, ",
|
|
27996
|
+
"i føremål å forbetre tenesta."
|
|
27997
|
+
],
|
|
27998
|
+
pl: [
|
|
27999
|
+
"W celu identyfikacji Explo przypisuje każdemu użytkownikowi adres e-mail i nazwę. ",
|
|
28000
|
+
"Poza tym Explo przechowuje tylko te informacje, które dobrowolnie wprowadzają sami ",
|
|
28001
|
+
"użytkownicy. Prowadzony jest rejestr ruchu internetowego i zdarzeń w Explo w celu ",
|
|
28002
|
+
"ulepszenia usługi."
|
|
28003
|
+
],
|
|
28004
|
+
ga: [
|
|
28005
|
+
"Chun aitheantais, ceanglaíonn Explo seoladh ríomhphoist agus ainm le gach úsáideoir. ",
|
|
28006
|
+
"Seachas sin, ní stóráiltear ag Explo ach an fhaisnéis a chuirtear isteach go deonach ",
|
|
28007
|
+
"ag na húsáideoirí iad féin. Coinnítear logáil ar thrácht gréasáin agus imeachtaí laistigh de Explo, ",
|
|
28008
|
+
"leis an gcuspóir an tseirbhís a fheabhsú."
|
|
28009
|
+
]
|
|
28010
|
+
};
|
|
28011
|
+
var welcome_1 = {
|
|
28012
|
+
is: [
|
|
28013
|
+
"Netskrafl notar Google Accounts innskráningu, þá sömu og er notuð m.a. í Gmail. ",
|
|
28014
|
+
"Til að auðkenna þig sem notanda og halda innskráningunni virkri ",
|
|
28015
|
+
"er óhjákvæmilegt að geyma þar til gerða smáköku (<i>cookie</i>) ",
|
|
28016
|
+
"í vafranum þínum."
|
|
28017
|
+
],
|
|
28018
|
+
en: [
|
|
28019
|
+
"Explo uses Google Accounts for user authentication, similarly to e.g. Gmail. ",
|
|
28020
|
+
"To remember your login and maintain your session, it is necessary to store a ",
|
|
28021
|
+
"cookie within your browser."
|
|
28022
|
+
],
|
|
28023
|
+
nb: [
|
|
28024
|
+
"Explo bruker Google-kontoer for brukerautentisering, likt som f.eks. Gmail. ",
|
|
28025
|
+
"For å huske din innlogging og opprettholde din økt, er det nødvendig å lagre en ",
|
|
28026
|
+
"informasjonskapsel i nettleseren din."
|
|
28027
|
+
],
|
|
28028
|
+
nn: [
|
|
28029
|
+
"Explo brukar Google-kontoar for brukarautentisering, likt som t.d. Gmail. ",
|
|
28030
|
+
"For å hugse innlogginga di og halde ved like økta di, er det naudsynt å lagre ein ",
|
|
28031
|
+
"informasjonskapsel i nettlesaren din."
|
|
28032
|
+
],
|
|
28033
|
+
pl: [
|
|
28034
|
+
"Explo używa kont Google do uwierzytelniania użytkownika, podobnie jak np. Gmail. ",
|
|
28035
|
+
"Aby zapamiętać twoje logowanie i utrzymać sesję, konieczne jest przechowanie ",
|
|
28036
|
+
"ciasteczka w twojej przeglądarce."
|
|
28037
|
+
],
|
|
28038
|
+
ga: [
|
|
28039
|
+
"Úsáideann Explo Cuntais Google le haghaidh fíordheimhniú úsáideora, cosúil le Gmail, mar shampla. ",
|
|
28040
|
+
"Chun do logáil isteach a mheabhrú agus do sheisiún a chothabháil, tá sé riachtanach fianán a stóráil ",
|
|
28041
|
+
"i do bhrabhsálaí."
|
|
28042
|
+
]
|
|
28043
|
+
};
|
|
28044
|
+
var welcome_0 = {
|
|
28045
|
+
is: [
|
|
28046
|
+
"Netskrafl er vettvangur ",
|
|
28047
|
+
"<b>yfir 40.000 íslenskra skraflara</b>",
|
|
28048
|
+
" á netinu."
|
|
28049
|
+
],
|
|
28050
|
+
en: [
|
|
28051
|
+
"Explo is a venue for ",
|
|
28052
|
+
"<b>tens of thousands of crossword game enthusiasts</b> ",
|
|
28053
|
+
"on the Internet."
|
|
28054
|
+
],
|
|
28055
|
+
nb: [
|
|
28056
|
+
"Explo er et møtested for ",
|
|
28057
|
+
"<b>tusenvis av kryssordspillentusiaster</b>",
|
|
28058
|
+
" på internett."
|
|
28059
|
+
],
|
|
28060
|
+
nn: [
|
|
28061
|
+
"Explo er ein møtestad for ",
|
|
28062
|
+
"<b>tusenvis av kryssordspelentusiastar</b>",
|
|
28063
|
+
" på internett."
|
|
28064
|
+
],
|
|
28065
|
+
pl: [
|
|
28066
|
+
"Explo to miejsce dla ",
|
|
28067
|
+
"<b>dziesiątek tysięcy entuzjastów gier krzyżówkowych</b>",
|
|
28068
|
+
" w Internecie."
|
|
28069
|
+
],
|
|
28070
|
+
ga: [
|
|
28071
|
+
"Is ionad é Explo do ",
|
|
28072
|
+
"<b>na deich mílte díograiseoirí cluiche crosfhocal</b>",
|
|
28073
|
+
" ar an Idirlíon."
|
|
28074
|
+
]
|
|
28075
|
+
};
|
|
28076
|
+
var Stigatafla = {
|
|
28077
|
+
en: "Leaderboard",
|
|
28078
|
+
nb: "Toppliste",
|
|
28079
|
+
nn: "Toppliste",
|
|
28080
|
+
pl: "Tabela wyników",
|
|
28081
|
+
ga: "Clár ceannairí"
|
|
28082
|
+
};
|
|
28083
|
+
var date_format = {
|
|
28084
|
+
is: "{day}. {month}",
|
|
28085
|
+
en: "{month} {day}",
|
|
28086
|
+
nb: "{day}. {month}",
|
|
28087
|
+
nn: "{day}. {month}",
|
|
28088
|
+
pl: "{day} {month}",
|
|
28089
|
+
ga: "{day} {month}"
|
|
28090
|
+
};
|
|
28091
|
+
var january = {
|
|
28092
|
+
is: "janúar",
|
|
28093
|
+
en: "January",
|
|
28094
|
+
nb: "januar",
|
|
28095
|
+
nn: "januar",
|
|
28096
|
+
pl: "styczeń",
|
|
28097
|
+
ga: "Eanáir"
|
|
28098
|
+
};
|
|
28099
|
+
var february = {
|
|
28100
|
+
is: "febrúar",
|
|
28101
|
+
en: "February",
|
|
28102
|
+
nb: "februar",
|
|
28103
|
+
nn: "februar",
|
|
28104
|
+
pl: "luty",
|
|
28105
|
+
ga: "Feabhra"
|
|
28106
|
+
};
|
|
28107
|
+
var march = {
|
|
28108
|
+
is: "mars",
|
|
28109
|
+
en: "March",
|
|
28110
|
+
nb: "mars",
|
|
28111
|
+
nn: "mars",
|
|
28112
|
+
pl: "marzec",
|
|
28113
|
+
ga: "Márta"
|
|
28114
|
+
};
|
|
28115
|
+
var april = {
|
|
28116
|
+
is: "apríl",
|
|
28117
|
+
en: "April",
|
|
28118
|
+
nb: "april",
|
|
28119
|
+
nn: "april",
|
|
28120
|
+
pl: "kwiecień",
|
|
28121
|
+
ga: "Aibreán"
|
|
28122
|
+
};
|
|
28123
|
+
var may = {
|
|
28124
|
+
is: "maí",
|
|
28125
|
+
en: "May",
|
|
28126
|
+
nb: "mai",
|
|
28127
|
+
nn: "mai",
|
|
28128
|
+
pl: "maj",
|
|
28129
|
+
ga: "Bealtaine"
|
|
28130
|
+
};
|
|
28131
|
+
var june = {
|
|
28132
|
+
is: "júní",
|
|
28133
|
+
en: "June",
|
|
28134
|
+
nb: "juni",
|
|
28135
|
+
nn: "juni",
|
|
28136
|
+
pl: "czerwiec",
|
|
28137
|
+
ga: "Meitheamh"
|
|
28138
|
+
};
|
|
28139
|
+
var july = {
|
|
28140
|
+
is: "júlí",
|
|
28141
|
+
en: "July",
|
|
28142
|
+
nb: "juli",
|
|
28143
|
+
nn: "juli",
|
|
28144
|
+
pl: "lipiec",
|
|
28145
|
+
ga: "Iúil"
|
|
28146
|
+
};
|
|
28147
|
+
var august = {
|
|
28148
|
+
is: "ágúst",
|
|
28149
|
+
en: "August",
|
|
28150
|
+
nb: "august",
|
|
28151
|
+
nn: "august",
|
|
28152
|
+
pl: "sierpień",
|
|
28153
|
+
ga: "Lúnasa"
|
|
28154
|
+
};
|
|
28155
|
+
var september = {
|
|
28156
|
+
is: "september",
|
|
28157
|
+
en: "September",
|
|
28158
|
+
nb: "september",
|
|
28159
|
+
nn: "september",
|
|
28160
|
+
pl: "wrzesień",
|
|
28161
|
+
ga: "Meán Fómhair"
|
|
28162
|
+
};
|
|
28163
|
+
var october = {
|
|
28164
|
+
is: "október",
|
|
28165
|
+
en: "October",
|
|
28166
|
+
nb: "oktober",
|
|
28167
|
+
nn: "oktober",
|
|
28168
|
+
pl: "październik",
|
|
28169
|
+
ga: "Deireadh Fómhair"
|
|
28170
|
+
};
|
|
28171
|
+
var november = {
|
|
28172
|
+
is: "nóvember",
|
|
28173
|
+
en: "November",
|
|
28174
|
+
nb: "november",
|
|
28175
|
+
nn: "november",
|
|
28176
|
+
pl: "listopad",
|
|
28177
|
+
ga: "Samhain"
|
|
28178
|
+
};
|
|
28179
|
+
var december = {
|
|
28180
|
+
is: "desember",
|
|
28181
|
+
en: "December",
|
|
28182
|
+
nb: "desember",
|
|
28183
|
+
nn: "desember",
|
|
28184
|
+
pl: "grudzień",
|
|
28185
|
+
ga: "Nollaig"
|
|
28186
|
+
};
|
|
28187
|
+
var messagesData = {
|
|
28188
|
+
Leikir: Leikir,
|
|
28189
|
+
submit_move: submit_move,
|
|
28190
|
+
"Viðureignir": {
|
|
28191
|
+
en: "Games",
|
|
28192
|
+
nb: "Spill",
|
|
28193
|
+
nn: "Spel",
|
|
28194
|
+
pl: "Gry",
|
|
28195
|
+
ga: "Cluichí"
|
|
28196
|
+
},
|
|
28197
|
+
"Borðið": {
|
|
28198
|
+
en: "Board",
|
|
28199
|
+
nb: "Brett",
|
|
28200
|
+
nn: "Brett",
|
|
28201
|
+
pl: "Plansza",
|
|
28202
|
+
ga: "Bord"
|
|
28203
|
+
},
|
|
28204
|
+
"Tveggja stafa orð": {
|
|
28205
|
+
en: "Two letter words",
|
|
28206
|
+
nb: "Tobokstavsord",
|
|
28207
|
+
nn: "Tobokstavsord",
|
|
28208
|
+
pl: "Dwuliterowe słowa",
|
|
28209
|
+
ga: "Focail dhá litir"
|
|
28210
|
+
},
|
|
28211
|
+
Spjall: Spjall,
|
|
28212
|
+
"Þessi vefslóð er ekki rétt": {
|
|
28213
|
+
en: "Unknown URL",
|
|
28214
|
+
nb: "Ukjent URL",
|
|
28215
|
+
nn: "Ukjend URL",
|
|
28216
|
+
pl: "Nieznany URL",
|
|
28217
|
+
ga: "URL Anaithnid"
|
|
28218
|
+
},
|
|
28219
|
+
player_info: player_info,
|
|
28220
|
+
"Einkenni:": {
|
|
28221
|
+
en: "User identifier:",
|
|
28222
|
+
nb: "Brukeridentifikator:",
|
|
28223
|
+
nn: "Brukaridentifikator:",
|
|
28224
|
+
pl: "Identyfikator użytkownika:",
|
|
28225
|
+
ga: "Aitheantóir Úsáideora:"
|
|
28226
|
+
},
|
|
28227
|
+
"Verður að vera útfyllt": {
|
|
28228
|
+
en: "Required field",
|
|
28229
|
+
nb: "Obligatorisk felt",
|
|
28230
|
+
nn: "Obligatorisk felt",
|
|
28231
|
+
pl: "Pole wymagane",
|
|
28232
|
+
ga: "Réimse Riachtanach"
|
|
28233
|
+
},
|
|
28234
|
+
"Fullt nafn:": {
|
|
28235
|
+
en: "Full name:",
|
|
28236
|
+
nb: "Fullt navn:",
|
|
28237
|
+
nn: "Fullt namn:",
|
|
28238
|
+
pl: "Pełne imię i nazwisko:",
|
|
28239
|
+
ga: "Ainm Iomlán:"
|
|
28240
|
+
},
|
|
28241
|
+
"Valfrjálst - sýnt í notendalistum Netskrafls": {
|
|
28242
|
+
en: "Optional - shown in user lists",
|
|
28243
|
+
nb: "Valgfritt - vist i brukerlister",
|
|
28244
|
+
nn: "Valfritt - vist i brukarlister",
|
|
28245
|
+
pl: "Opcjonalne - pokazane na listach użytkowników",
|
|
28246
|
+
ga: "Roghnach - le feiceáil i liostaí úsáideoirí"
|
|
28247
|
+
},
|
|
28248
|
+
"Tölvupóstfang:": {
|
|
28249
|
+
en: "E-mail:",
|
|
28250
|
+
nb: "E-post:",
|
|
28251
|
+
nn: "E-post:",
|
|
28252
|
+
pl: "E-mail:",
|
|
28253
|
+
ga: "Ríomhphost:"
|
|
28254
|
+
},
|
|
28255
|
+
explain_email: explain_email,
|
|
28256
|
+
"Hljóðmerki:": {
|
|
28257
|
+
en: "Sounds:",
|
|
28258
|
+
nb: "Lyder:",
|
|
28259
|
+
nn: "Lydar:",
|
|
28260
|
+
pl: "Dźwięki:",
|
|
28261
|
+
ga: "Fuaimeanna:"
|
|
28262
|
+
},
|
|
28263
|
+
"Hljóð á/af": {
|
|
28264
|
+
en: "Sound on/off",
|
|
28265
|
+
nb: "Lyd på/av",
|
|
28266
|
+
nn: "Lyd på/av",
|
|
28267
|
+
pl: "Dźwięki włącz/wyłącz",
|
|
28268
|
+
ga: "Fuaimeanna ar/amuigh"
|
|
28269
|
+
},
|
|
28270
|
+
"Lúðraþytur eftir sigur:": {
|
|
28271
|
+
en: "Fanfare after a win:",
|
|
28272
|
+
nb: "Trompeter etter seier:",
|
|
28273
|
+
nn: "Trompeter etter siger:",
|
|
28274
|
+
pl: "Trąbki po zwycięstwie:",
|
|
28275
|
+
ga: "Trumpaí tar éis bua:"
|
|
28276
|
+
},
|
|
28277
|
+
"Lúðraþytur á/af": {
|
|
28278
|
+
en: "Fanfare on/off",
|
|
28279
|
+
nb: "Trompeter på/av",
|
|
28280
|
+
nn: "Trompeter på/av",
|
|
28281
|
+
pl: "Trąbki włącz/wyłącz",
|
|
28282
|
+
ga: "Trumpaí ar/amuigh"
|
|
28283
|
+
},
|
|
28284
|
+
explain_sound: explain_sound,
|
|
28285
|
+
"Sýna reitagildi:": {
|
|
28286
|
+
en: "Show multipliers:",
|
|
28287
|
+
nb: "Vis multiplikatorer:",
|
|
28288
|
+
nn: "Vis multiplikatorar:",
|
|
28289
|
+
pl: "Pokaż mnożniki:",
|
|
28290
|
+
ga: "Taispeáin iolraitheoirí:"
|
|
28291
|
+
},
|
|
28292
|
+
"Nýi skraflpokinn:": {
|
|
28293
|
+
en: "Use the new bag:",
|
|
28294
|
+
nb: "Bruk den nye posen:",
|
|
28295
|
+
nn: "Bruk den nye posen:",
|
|
28296
|
+
pl: "Użyj nowego worka:",
|
|
28297
|
+
ga: "Bain úsáid as an mála nua:"
|
|
28298
|
+
},
|
|
28299
|
+
"Án hjálpartækja:": {
|
|
28300
|
+
en: "Without helpers:",
|
|
28301
|
+
nb: "Uten hjelpemidler:",
|
|
28302
|
+
nn: "Utan hjelpemiddel:",
|
|
28303
|
+
pl: "Bez pomocy:",
|
|
28304
|
+
ga: "Gan chúntóirí:"
|
|
28305
|
+
},
|
|
28306
|
+
Vista: Vista,
|
|
28307
|
+
"Hætta við": {
|
|
28308
|
+
en: "Cancel",
|
|
28309
|
+
nb: "Avbryt",
|
|
28310
|
+
nn: "Bryt av",
|
|
28311
|
+
pl: "Anuluj",
|
|
28312
|
+
ga: "Cealaigh"
|
|
28313
|
+
},
|
|
28314
|
+
"Skrá mig út": {
|
|
28315
|
+
en: "Log out",
|
|
28316
|
+
nb: "Logg ut",
|
|
28317
|
+
nn: "Logg ut",
|
|
28318
|
+
pl: "Wyloguj się",
|
|
28319
|
+
ga: "Logáil Amach"
|
|
28320
|
+
},
|
|
28321
|
+
"Þú ert áskrifandi!": {
|
|
28322
|
+
en: "You're a subscriber!",
|
|
28323
|
+
nb: "Du er en abonnent!",
|
|
28324
|
+
nn: "Du er ein abonnent!",
|
|
28325
|
+
pl: "Jesteś subskrybentem!",
|
|
28326
|
+
ga: "Is síntiúsóir tú!"
|
|
28327
|
+
},
|
|
28328
|
+
"Gerast áskrifandi": {
|
|
28329
|
+
en: "Subscribe",
|
|
28330
|
+
nb: "Abonner",
|
|
28331
|
+
nn: "Abonner",
|
|
28332
|
+
pl: "Subskrybuj",
|
|
28333
|
+
ga: "Liostáil"
|
|
28334
|
+
},
|
|
28335
|
+
"Tek við áskorunum!": {
|
|
28336
|
+
en: "Accepting challenges!",
|
|
28337
|
+
nb: "Aksepterer utfordringer!",
|
|
28338
|
+
nn: "Tek imot utfordringar!",
|
|
28339
|
+
pl: "Akceptuje wyzwania!",
|
|
28340
|
+
ga: "Ag glacadh le dúshláin!"
|
|
28341
|
+
},
|
|
28342
|
+
"Til í viðureign með klukku!": {
|
|
28343
|
+
en: "Ready for timed games!",
|
|
28344
|
+
nb: "Klar for tidsbegrensede spill!",
|
|
28345
|
+
nn: "Klar for tidsavgrensa spel!",
|
|
28346
|
+
pl: "Gotowy na gry z czasem!",
|
|
28347
|
+
ga: "Réidh do chluichí ama!"
|
|
28348
|
+
},
|
|
28349
|
+
"Stillir hvort ": {
|
|
28350
|
+
en: "Controls whether ",
|
|
28351
|
+
nb: "Kontrollerer om ",
|
|
28352
|
+
nn: "Styrer om ",
|
|
28353
|
+
pl: "Kontroluje czy ",
|
|
28354
|
+
ga: "Rialaíonn sé an "
|
|
28355
|
+
},
|
|
28356
|
+
"minnismiði": {
|
|
28357
|
+
en: "a memo sticker",
|
|
28358
|
+
nb: "en huskelapp",
|
|
28359
|
+
nn: "ein hugselapp",
|
|
28360
|
+
pl: "naklejka memo",
|
|
28361
|
+
ga: "nóta meabhrúcháin"
|
|
28362
|
+
},
|
|
28363
|
+
" um margföldunargildi reita er sýndur við borðið": {
|
|
28364
|
+
en: " with square multipliers is shown beside the board",
|
|
28365
|
+
nb: " med rute-multiplikatorer vises ved siden av brettet",
|
|
28366
|
+
nn: " med rute-multiplikatorar blir vist ved sida av brettet",
|
|
28367
|
+
pl: " z mnożnikami kwadratów jest pokazany obok planszy",
|
|
28368
|
+
ga: " le hiolraitheoirí cearnóg le feiceáil in aice leis an mbord"
|
|
28369
|
+
},
|
|
28370
|
+
"Gefur til kynna hvort þú sért reiðubúin(n) að\nskrafla með ": {
|
|
28371
|
+
en: "Indicates whether you are ready to play with\n",
|
|
28372
|
+
nb: "Indikerer om du er klar til å spille med\n",
|
|
28373
|
+
nn: "Indikerer om du er klar til å spele med\n",
|
|
28374
|
+
pl: "Wskazuje czy jesteś gotowy do gry z\n",
|
|
28375
|
+
ga: "Léiríonn sé an bhfuil tú ullamh chun imeartha le\n"
|
|
28376
|
+
},
|
|
28377
|
+
"nýja íslenska skraflpokanum": {
|
|
28378
|
+
en: "the new tile bag",
|
|
28379
|
+
nb: "den nye brikkeposen",
|
|
28380
|
+
nn: "den nye brikkeposen",
|
|
28381
|
+
pl: "nowym workiem z kafelkami",
|
|
28382
|
+
ga: "an mála tíleanna nua"
|
|
28383
|
+
},
|
|
28384
|
+
no_helpers: no_helpers,
|
|
28385
|
+
"án stafrænna hjálpartækja": {
|
|
28386
|
+
en: "without helpers or tools",
|
|
28387
|
+
nb: "uten hjelpemidler eller verktøy",
|
|
28388
|
+
nn: "utan hjelpemiddel eller verktøy",
|
|
28389
|
+
pl: "bez pomocy lub narzędzi",
|
|
28390
|
+
ga: "gan chúntóirí ná uirlisí"
|
|
28391
|
+
},
|
|
28392
|
+
" af nokkru tagi": {
|
|
28393
|
+
en: " of any kind",
|
|
28394
|
+
nb: " av noe slag",
|
|
28395
|
+
nn: " av noko slag",
|
|
28396
|
+
pl: " jakiegokolwiek rodzaju",
|
|
28397
|
+
ga: " de chineál ar bith"
|
|
28398
|
+
},
|
|
28399
|
+
"Áskoranir": {
|
|
28400
|
+
en: "Challenges",
|
|
28401
|
+
nb: "Utfordringer",
|
|
28402
|
+
nn: "Utfordringar",
|
|
28403
|
+
pl: "Wyzwania",
|
|
28404
|
+
ga: "Dúshláin"
|
|
28405
|
+
},
|
|
28406
|
+
"Andstæðingar": {
|
|
28407
|
+
en: "Opponents",
|
|
28408
|
+
nb: "Motstandere",
|
|
28409
|
+
nn: "Motstandarar",
|
|
28410
|
+
pl: "Przeciwnicy",
|
|
28411
|
+
ga: "Freasúra"
|
|
28412
|
+
},
|
|
28413
|
+
Ferill: Ferill,
|
|
28414
|
+
"Þú átt leik": {
|
|
28415
|
+
en: "Your turn",
|
|
28416
|
+
nb: "Din tur",
|
|
28417
|
+
nn: "Din tur",
|
|
28418
|
+
pl: "Twoja kolej",
|
|
28419
|
+
ga: "Do sheal"
|
|
28420
|
+
},
|
|
28421
|
+
"Viðureign lokið": {
|
|
28422
|
+
en: "Game over",
|
|
28423
|
+
nb: "Spillet er over",
|
|
28424
|
+
nn: "Spelet er over",
|
|
28425
|
+
pl: "Koniec gry",
|
|
28426
|
+
ga: "Cluiche thart"
|
|
28427
|
+
},
|
|
28428
|
+
opp_move: opp_move,
|
|
28429
|
+
"Átt þú leik?": {
|
|
28430
|
+
en: "Your turn?",
|
|
28431
|
+
nb: "Din tur?",
|
|
28432
|
+
nn: "Din tur?",
|
|
28433
|
+
pl: "Twoja kolej?",
|
|
28434
|
+
ga: "Do sheal?"
|
|
28435
|
+
},
|
|
28436
|
+
"Langt frá síðasta leik?": {
|
|
28437
|
+
en: "Long time elapsed since last move?",
|
|
28438
|
+
nb: "Lang tid siden siste trekk?",
|
|
28439
|
+
nn: "Lang tid sidan siste trekk?",
|
|
28440
|
+
pl: "Dużo czasu minęło od ostatniego ruchu?",
|
|
28441
|
+
ga: "An bhfuil am fada caite ón mbogadh deireanach?"
|
|
28442
|
+
},
|
|
28443
|
+
"Síðasti leikur": {
|
|
28444
|
+
en: "Last move",
|
|
28445
|
+
nb: "Siste trekk",
|
|
28446
|
+
nn: "Siste trekk",
|
|
28447
|
+
pl: "Ostatni ruch",
|
|
28448
|
+
ga: "Bogadh deireanach"
|
|
28449
|
+
},
|
|
28450
|
+
"Andstæðingur": {
|
|
28451
|
+
en: "Opponent",
|
|
28452
|
+
nb: "Motstander",
|
|
28453
|
+
nn: "Motstandar",
|
|
28454
|
+
pl: "Przeciwnik",
|
|
28455
|
+
ga: "Iomaitheoir"
|
|
28456
|
+
},
|
|
28457
|
+
"Staða": {
|
|
28458
|
+
en: "Score",
|
|
28459
|
+
nb: "Poengsum",
|
|
28460
|
+
nn: "Poengsum",
|
|
28461
|
+
pl: "Wynik",
|
|
28462
|
+
ga: "Scór"
|
|
28463
|
+
},
|
|
28464
|
+
Framvinda: Framvinda,
|
|
28465
|
+
Keppnishamur: Keppnishamur,
|
|
28466
|
+
"Venjuleg ótímabundin viðureign": {
|
|
28467
|
+
en: "Standard Mode without time limit",
|
|
28468
|
+
nb: "Standardmodus uten tidsbegrensning",
|
|
28469
|
+
nn: "Standardmodus utan tidsbegrensing",
|
|
28470
|
+
pl: "Tryb standardowy bez limitu czasu",
|
|
28471
|
+
ga: "Gnáthchluiche gan teorainn ama"
|
|
28472
|
+
},
|
|
28473
|
+
with_clock: with_clock,
|
|
28474
|
+
Hafna: Hafna,
|
|
28475
|
+
Afturkalla: Afturkalla,
|
|
28476
|
+
"Án hjálpartækja": {
|
|
28477
|
+
en: "Without helpers",
|
|
28478
|
+
nb: "Uten hjelpemidler",
|
|
28479
|
+
nn: "Utan hjelpemiddel",
|
|
28480
|
+
pl: "Bez pomocy",
|
|
28481
|
+
ga: "Gan chúntóirí"
|
|
28482
|
+
},
|
|
28483
|
+
"Skoða feril": {
|
|
28484
|
+
en: "View history",
|
|
28485
|
+
nb: "Vis historikk",
|
|
28486
|
+
nn: "Vis historikk",
|
|
28487
|
+
pl: "Zobacz historię",
|
|
28488
|
+
ga: "Féach ar stair"
|
|
28489
|
+
},
|
|
28490
|
+
"Gamli pokinn": {
|
|
28491
|
+
en: "Old tile bag",
|
|
28492
|
+
nb: "Gammel brikkepose",
|
|
28493
|
+
nn: "Gammal brikkepose",
|
|
28494
|
+
pl: "Stary worek z kafelkami",
|
|
28495
|
+
ga: "Mála tíleanna sean"
|
|
28496
|
+
},
|
|
28497
|
+
"Hvenær": {
|
|
28498
|
+
en: "When",
|
|
28499
|
+
nb: "Når",
|
|
28500
|
+
nn: "Når",
|
|
28501
|
+
pl: "Kiedy",
|
|
28502
|
+
ga: "Cathain"
|
|
28503
|
+
},
|
|
28504
|
+
"Áskorandi": {
|
|
28505
|
+
en: "Challenger",
|
|
28506
|
+
nb: "Utfordrer",
|
|
28507
|
+
nn: "Utfordrar",
|
|
28508
|
+
pl: "Wyzwający",
|
|
28509
|
+
ga: "Dúshlánóir"
|
|
28510
|
+
},
|
|
28511
|
+
Hvernig: Hvernig,
|
|
28512
|
+
Sigur: Sigur,
|
|
28513
|
+
Jafntefli: Jafntefli,
|
|
28514
|
+
Tap: Tap,
|
|
28515
|
+
"Úrslit": {
|
|
28516
|
+
en: "Result",
|
|
28517
|
+
nb: "Resultat",
|
|
28518
|
+
nn: "Resultat",
|
|
28519
|
+
pl: "Wynik",
|
|
28520
|
+
ga: "Toradh"
|
|
28521
|
+
},
|
|
28522
|
+
"Viðureign lauk": {
|
|
28523
|
+
en: "Game finished",
|
|
28524
|
+
nb: "Spill avsluttet",
|
|
28525
|
+
nn: "Spel avslutta",
|
|
28526
|
+
pl: "Gra zakończona",
|
|
28527
|
+
ga: "Cluiche críochnaithe"
|
|
28528
|
+
},
|
|
28529
|
+
"Mennskir andstæðingar": {
|
|
28530
|
+
en: "Human opponents",
|
|
28531
|
+
nb: "Menneskelige motstandere",
|
|
28532
|
+
nn: "Menneskelege motstandarar",
|
|
28533
|
+
pl: "Ludzcy przeciwnicy",
|
|
28534
|
+
ga: "Freasúra daonna"
|
|
28535
|
+
},
|
|
28536
|
+
"Allir andstæðingar": {
|
|
28537
|
+
en: "All opponents",
|
|
28538
|
+
nb: "Alle motstandere",
|
|
28539
|
+
nn: "Alle motstandarar",
|
|
28540
|
+
pl: "Wszyscy przeciwnicy",
|
|
28541
|
+
ga: "Gach freasúra"
|
|
28542
|
+
},
|
|
28543
|
+
Elo: Elo,
|
|
28544
|
+
Lengd: Lengd,
|
|
28545
|
+
"Uppáhald": {
|
|
28546
|
+
en_US: "Favorite",
|
|
28547
|
+
en: "Favourite",
|
|
28548
|
+
nb: "Favoritt",
|
|
28549
|
+
nn: "Favoritt",
|
|
28550
|
+
pl: "Ulubione",
|
|
28551
|
+
ga: "Is fearr leat"
|
|
28552
|
+
},
|
|
28553
|
+
"Uppáhalds": {
|
|
28554
|
+
en_US: "Favorites",
|
|
28555
|
+
en: "Favourites",
|
|
28556
|
+
nb: "Favoritter",
|
|
28557
|
+
nn: "Favorittar",
|
|
28558
|
+
pl: "Ulubione",
|
|
28559
|
+
ga: "Roghanna"
|
|
28560
|
+
},
|
|
28561
|
+
"Skora á": {
|
|
28562
|
+
en: "Challenge",
|
|
28563
|
+
nb: "Utfordre",
|
|
28564
|
+
nn: "Utfordre",
|
|
28565
|
+
pl: "Wyzwanie",
|
|
28566
|
+
ga: "Dúshlán"
|
|
28567
|
+
},
|
|
28568
|
+
Einkenni: Einkenni,
|
|
28569
|
+
"Nafn og merki": {
|
|
28570
|
+
en: "Full name and badges",
|
|
28571
|
+
nb: "Fullt navn og merker",
|
|
28572
|
+
nn: "Fullt namn og merke",
|
|
28573
|
+
pl: "Pełna nazwa i odznaki",
|
|
28574
|
+
ga: "Ainm iomlán agus suaitheantais"
|
|
28575
|
+
},
|
|
28576
|
+
" finnst ekki": {
|
|
28577
|
+
en: " not found",
|
|
28578
|
+
nb: " ikke funnet",
|
|
28579
|
+
nn: " ikkje funne",
|
|
28580
|
+
pl: " nie znaleziono",
|
|
28581
|
+
ga: " gan aimsiú"
|
|
28582
|
+
},
|
|
28583
|
+
"Þjarkar": {
|
|
28584
|
+
en: "Robots",
|
|
28585
|
+
nb: "Roboter",
|
|
28586
|
+
nn: "Robotar",
|
|
28587
|
+
pl: "Roboty",
|
|
28588
|
+
ga: "Róbónna"
|
|
28589
|
+
},
|
|
28590
|
+
"Álínis": {
|
|
28591
|
+
en: "Online",
|
|
28592
|
+
nb: "Pålogget",
|
|
28593
|
+
nn: "Pålogga",
|
|
28594
|
+
pl: "Online",
|
|
28595
|
+
ga: "Ar líne"
|
|
28596
|
+
},
|
|
28597
|
+
"Svipaðir": {
|
|
28598
|
+
en: "Similar",
|
|
28599
|
+
nb: "Lignende",
|
|
28600
|
+
nn: "Liknande",
|
|
28601
|
+
pl: "Podobne",
|
|
28602
|
+
ga: "Cosúil"
|
|
28603
|
+
},
|
|
28604
|
+
"Topp 100": {
|
|
28605
|
+
en: "Top 100",
|
|
28606
|
+
nb: "Topp 100",
|
|
28607
|
+
nn: "Topp 100",
|
|
28608
|
+
pl: "Top 100",
|
|
28609
|
+
ga: "Barr 100"
|
|
28610
|
+
},
|
|
28611
|
+
"orð": {
|
|
28612
|
+
en: "word",
|
|
28613
|
+
nb: "ord",
|
|
28614
|
+
nn: "ord",
|
|
28615
|
+
pl: "słowo",
|
|
28616
|
+
ga: "focal"
|
|
28617
|
+
},
|
|
28618
|
+
stafur: stafur,
|
|
28619
|
+
Senda: Senda,
|
|
28620
|
+
Pass: Pass,
|
|
28621
|
+
letter: letter,
|
|
28622
|
+
letters: letters,
|
|
28623
|
+
exchanged: exchanged,
|
|
28624
|
+
"Gaf viðureign": {
|
|
28625
|
+
en: "Resigned",
|
|
28626
|
+
nb: "Ga opp",
|
|
28627
|
+
nn: "Gav opp",
|
|
28628
|
+
pl: "Zrezygnował",
|
|
28629
|
+
ga: "D'éirigh as"
|
|
28630
|
+
},
|
|
28631
|
+
"Véfengdi lögn": {
|
|
28632
|
+
en: "Challenged move",
|
|
28633
|
+
nb: "Utfordret trekk",
|
|
28634
|
+
nn: "Utfordra trekk",
|
|
28635
|
+
pl: "Ruch zakwestionowany",
|
|
28636
|
+
ga: "Bogadh dúshlánach"
|
|
28637
|
+
},
|
|
28638
|
+
"Óleyfileg lögn": {
|
|
28639
|
+
en: "Invalid move",
|
|
28640
|
+
nb: "Ugyldig trekk",
|
|
28641
|
+
nn: "Ugyldig trekk",
|
|
28642
|
+
pl: "Nieprawidłowy ruch",
|
|
28643
|
+
ga: "Bogadh neamhbhailí"
|
|
28644
|
+
},
|
|
28645
|
+
"Röng véfenging": {
|
|
28646
|
+
en: "Unsuccessful challenge",
|
|
28647
|
+
nb: "Mislykket utfordring",
|
|
28648
|
+
nn: "Mislukka utfordring",
|
|
28649
|
+
pl: "Nieudane wyzwanie",
|
|
28650
|
+
ga: "Dúshlán gan rath"
|
|
28651
|
+
},
|
|
28652
|
+
"Umframtími": {
|
|
28653
|
+
en: "Extra time",
|
|
28654
|
+
nb: "Ekstra tid",
|
|
28655
|
+
nn: "Ekstra tid",
|
|
28656
|
+
pl: "Dodatkowy czas",
|
|
28657
|
+
ga: "Am breise"
|
|
28658
|
+
},
|
|
28659
|
+
"Stafaleif: engin": {
|
|
28660
|
+
en: "Rack leave: none",
|
|
28661
|
+
nb: "Rack forlater: ingen",
|
|
28662
|
+
nn: "Stativ forlèt: ingen",
|
|
28663
|
+
pl: "Pozostawienie na stojaku: brak",
|
|
28664
|
+
ga: "Fágáil raca: dada"
|
|
28665
|
+
},
|
|
28666
|
+
"Stafaleif: ": {
|
|
28667
|
+
en: "Rack leave: ",
|
|
28668
|
+
nb: "Rack forlater: ",
|
|
28669
|
+
nn: "Stativ forlèt: ",
|
|
28670
|
+
pl: "Pozostawienie na stojaku: ",
|
|
28671
|
+
ga: "Fágáil raca: "
|
|
28672
|
+
},
|
|
28673
|
+
"Ný áskorun": {
|
|
28674
|
+
en: "New challenge",
|
|
28675
|
+
nb: "Ny utfordring",
|
|
28676
|
+
nn: "Ny utfordring",
|
|
28677
|
+
pl: "Nowe wyzwanie",
|
|
28678
|
+
ga: "Dúshlán nua"
|
|
28679
|
+
},
|
|
28680
|
+
"Viðureign án klukku": {
|
|
28681
|
+
en: "Game with no time limit",
|
|
28682
|
+
nb: "Spill uten tidsbegrensning",
|
|
28683
|
+
nn: "Spel utan tidsbegrensing",
|
|
28684
|
+
pl: "Gra bez limitu czasu",
|
|
28685
|
+
ga: "Cluiche gan teorainn ama"
|
|
28686
|
+
},
|
|
28687
|
+
"Nota ": {
|
|
28688
|
+
en: "Enable ",
|
|
28689
|
+
nb: "Aktiver ",
|
|
28690
|
+
nn: "Aktiver ",
|
|
28691
|
+
pl: "Włącz ",
|
|
28692
|
+
ga: "Cumasaigh "
|
|
28693
|
+
},
|
|
28694
|
+
"handvirka véfengingu": {
|
|
28695
|
+
en: "manual challenges",
|
|
28696
|
+
nb: "manuelle utfordringer",
|
|
28697
|
+
nn: "manuelle utfordringar",
|
|
28698
|
+
pl: "ręczne wyzwania",
|
|
28699
|
+
ga: "dúshláin láimhe"
|
|
28700
|
+
},
|
|
28701
|
+
"(\"keppnishamur\")": {
|
|
28702
|
+
en: "(\"Pro mode\")",
|
|
28703
|
+
nb: "(\"Pro-modus\")",
|
|
28704
|
+
nn: "(\"Pro-modus\")",
|
|
28705
|
+
pl: "(\"Tryb Pro\")",
|
|
28706
|
+
ga: "(\"Modh Pro\")"
|
|
28707
|
+
},
|
|
28708
|
+
"Viðureignir sem standa yfir": {
|
|
28709
|
+
en: "Games in progress",
|
|
28710
|
+
nb: "Pågående spill",
|
|
28711
|
+
nn: "Pågåande spel",
|
|
28712
|
+
pl: "Trwające gry",
|
|
28713
|
+
ga: "Cluichí ar siúl"
|
|
28714
|
+
},
|
|
28715
|
+
click_on_game: click_on_game,
|
|
28716
|
+
" þú átt leik": {
|
|
28717
|
+
en: " it's your turn",
|
|
28718
|
+
nb: " det er din tur",
|
|
28719
|
+
nn: " det er din tur",
|
|
28720
|
+
pl: " to twoja kolej",
|
|
28721
|
+
ga: " tá sé do sheal"
|
|
28722
|
+
},
|
|
28723
|
+
"Skorað á þig": {
|
|
28724
|
+
en: "Other players have challenged you",
|
|
28725
|
+
nb: "Andre spillere har utfordret deg",
|
|
28726
|
+
nn: "Andre spelarar har utfordra deg",
|
|
28727
|
+
pl: "Inni gracze wyzwali cię",
|
|
28728
|
+
ga: "Tá dúshláin curtha ort ag imreoirí eile"
|
|
28729
|
+
},
|
|
28730
|
+
click_on_challenge: click_on_challenge,
|
|
28731
|
+
" til að hafna henni": {
|
|
28732
|
+
en: " to decline it",
|
|
28733
|
+
nb: " for å avslå det",
|
|
28734
|
+
nn: " for å avslå det",
|
|
28735
|
+
pl: " aby je odrzucić",
|
|
28736
|
+
ga: " chun é a dhiúltú"
|
|
28737
|
+
},
|
|
28738
|
+
"Þú skorar á aðra": {
|
|
28739
|
+
en: "You challenge other players",
|
|
28740
|
+
nb: "Du utfordrer andre spillere",
|
|
28741
|
+
nn: "Du utfordrar andre spelarar",
|
|
28742
|
+
pl: "Wyzwasz innych graczy",
|
|
28743
|
+
ga: "Dúshlánaíonn tú imreoirí eile"
|
|
28744
|
+
},
|
|
28745
|
+
" - smelltu á ": {
|
|
28746
|
+
en: " - click on ",
|
|
28747
|
+
nb: " - klikk på ",
|
|
28748
|
+
nn: " - klikk på ",
|
|
28749
|
+
pl: " - kliknij na ",
|
|
28750
|
+
ga: " - cliceáil ar "
|
|
28751
|
+
},
|
|
28752
|
+
" til að afturkalla áskorun": {
|
|
28753
|
+
en: " to retract an issued challenge",
|
|
28754
|
+
nb: " for å trekke tilbake en utfordring",
|
|
28755
|
+
nn: " for å trekkje tilbake ei utfordring",
|
|
28756
|
+
pl: " aby wycofać wydane wyzwanie",
|
|
28757
|
+
ga: " chun dúshlán eisithe a tharraingt siar"
|
|
28758
|
+
},
|
|
28759
|
+
"Nýlegar viðureignir þínar": {
|
|
28760
|
+
en: "Your recent games",
|
|
28761
|
+
nb: "Dine nylige spill",
|
|
28762
|
+
nn: "Dine nylege spel",
|
|
28763
|
+
pl: "Twoje ostatnie gry",
|
|
28764
|
+
ga: "Do chluichí le déanaí"
|
|
28765
|
+
},
|
|
28766
|
+
click_to_review: click_to_review,
|
|
28767
|
+
"Einkenni eða nafn": {
|
|
28768
|
+
en: "Identifier or name",
|
|
28769
|
+
nb: "Identifikator eller navn",
|
|
28770
|
+
nn: "Identifikator eller namn",
|
|
28771
|
+
pl: "Identyfikator lub nazwa",
|
|
28772
|
+
ga: "Aitheantóir nó ainm"
|
|
28773
|
+
},
|
|
28774
|
+
"Upplýsingar og hjálp": {
|
|
28775
|
+
en: "Information and help",
|
|
28776
|
+
nb: "Informasjon og hjelp",
|
|
28777
|
+
nn: "Informasjon og hjelp",
|
|
28778
|
+
pl: "Informacje i pomoc",
|
|
28779
|
+
ga: "Eolas agus cabhair"
|
|
28780
|
+
},
|
|
28781
|
+
"1 dagur": {
|
|
28782
|
+
en: "1 day",
|
|
28783
|
+
nb: "1 dag",
|
|
28784
|
+
nn: "1 dag",
|
|
28785
|
+
pl: "1 dzień",
|
|
28786
|
+
ga: "1 lá"
|
|
28787
|
+
},
|
|
28788
|
+
" dagar": {
|
|
28789
|
+
en: " days",
|
|
28790
|
+
nb: " dager",
|
|
28791
|
+
nn: " dagar",
|
|
28792
|
+
pl: " dni",
|
|
28793
|
+
ga: " laethanta"
|
|
28794
|
+
},
|
|
28795
|
+
" og ": {
|
|
28796
|
+
en: " and ",
|
|
28797
|
+
nb: " og ",
|
|
28798
|
+
nn: " og ",
|
|
28799
|
+
pl: " i ",
|
|
28800
|
+
ga: " agus "
|
|
28801
|
+
},
|
|
28802
|
+
"1 klst": {
|
|
28803
|
+
en: "1 hour",
|
|
28804
|
+
nb: "1 time",
|
|
28805
|
+
nn: "1 time",
|
|
28806
|
+
pl: "1 godzina",
|
|
28807
|
+
ga: "1 uair"
|
|
28808
|
+
},
|
|
28809
|
+
" klst": {
|
|
28810
|
+
en: " hours",
|
|
28811
|
+
nb: " timer",
|
|
28812
|
+
nn: " timar",
|
|
28813
|
+
pl: " godzin",
|
|
28814
|
+
ga: " uair an chloig"
|
|
28815
|
+
},
|
|
28816
|
+
"1 mínúta": {
|
|
28817
|
+
en: "1 minute",
|
|
28818
|
+
nb: "1 minutt",
|
|
28819
|
+
nn: "1 minutt",
|
|
28820
|
+
pl: "1 minuta",
|
|
28821
|
+
ga: "1 nóiméad"
|
|
28822
|
+
},
|
|
28823
|
+
" mínútur": {
|
|
28824
|
+
en: " minutes",
|
|
28825
|
+
nb: " minutter",
|
|
28826
|
+
nn: " minutt",
|
|
28827
|
+
pl: " minuty",
|
|
28828
|
+
ga: " nóiméad"
|
|
28829
|
+
},
|
|
28830
|
+
"Viðureign með klukku": {
|
|
28831
|
+
en: "Timed game",
|
|
28832
|
+
nb: "Tidsbegrenset spill",
|
|
28833
|
+
nn: "Tidsbegrensa spel",
|
|
28834
|
+
pl: "Gra zegarowa",
|
|
28835
|
+
ga: "Cluiche ama"
|
|
28836
|
+
},
|
|
28837
|
+
"Áskrifandi": {
|
|
28838
|
+
en: "Subscriber",
|
|
28839
|
+
nb: "Abonnent",
|
|
28840
|
+
nn: "Abonnent",
|
|
28841
|
+
pl: "Subskrybent",
|
|
28842
|
+
ga: "Síntiúsóir"
|
|
28843
|
+
},
|
|
28844
|
+
"Nýjustu viðureignir": {
|
|
28845
|
+
en: "Recent games",
|
|
28846
|
+
nb: "Nylige spill",
|
|
28847
|
+
nn: "Nylege spel",
|
|
28848
|
+
pl: "Najnowsze gry",
|
|
28849
|
+
ga: "Cluichí is déanaí"
|
|
28850
|
+
},
|
|
28851
|
+
Loka: Loka,
|
|
28852
|
+
"Besta orð ": {
|
|
28853
|
+
en: "Best word ",
|
|
28854
|
+
nb: "Beste ord ",
|
|
28855
|
+
nn: "Beste ord ",
|
|
28856
|
+
pl: "Najlepsze słowo ",
|
|
28857
|
+
ga: "An focal is fearr "
|
|
28858
|
+
},
|
|
28859
|
+
"Hæsta skor ": {
|
|
28860
|
+
en: "Highest score ",
|
|
28861
|
+
nb: "Høyeste poengsum ",
|
|
28862
|
+
nn: "Høgaste poengsum ",
|
|
28863
|
+
pl: "Najwyższy wynik ",
|
|
28864
|
+
ga: "An scór is airde "
|
|
28865
|
+
},
|
|
28866
|
+
" stig": {
|
|
28867
|
+
en: " points",
|
|
28868
|
+
nb: " poeng",
|
|
28869
|
+
nn: " poeng",
|
|
28870
|
+
pl: " punkty",
|
|
28871
|
+
ga: " pointí"
|
|
28872
|
+
},
|
|
28873
|
+
"Til hamingju með sigurinn!": {
|
|
28874
|
+
en: "You won - congratulations!",
|
|
28875
|
+
nb: "Du vant - gratulerer!",
|
|
28876
|
+
nn: "Du vann - gratulerer!",
|
|
28877
|
+
pl: "Wygrałeś - gratulacje!",
|
|
28878
|
+
ga: "Bhuaigh tú - comhghairdeas!"
|
|
28879
|
+
},
|
|
28880
|
+
"Viðureigninni er lokið": {
|
|
28881
|
+
en: "Game over",
|
|
28882
|
+
nb: "Spillet er over",
|
|
28883
|
+
nn: "Spelet er over",
|
|
28884
|
+
pl: "Gra zakończona",
|
|
28885
|
+
ga: "Cluiche thart"
|
|
28886
|
+
},
|
|
28887
|
+
opponent_emptied_rack: opponent_emptied_rack,
|
|
28888
|
+
"Viltu gefa leikinn?": {
|
|
28889
|
+
en: "Do you want to resign the game?",
|
|
28890
|
+
nb: "Ønsker du å gi opp spillet?",
|
|
28891
|
+
nn: "Ønskjer du å gje opp spelet?",
|
|
28892
|
+
pl: "Czy chcesz zrezygnować z gry?",
|
|
28893
|
+
ga: "Ar mhaith leat éirí as an gcluiche?"
|
|
28894
|
+
},
|
|
28895
|
+
" Já": {
|
|
28896
|
+
en: " Yes",
|
|
28897
|
+
nb: " Ja",
|
|
28898
|
+
nn: " Ja",
|
|
28899
|
+
pl: " Tak",
|
|
28900
|
+
ga: " Tá"
|
|
28901
|
+
},
|
|
28902
|
+
" Nei": {
|
|
28903
|
+
en: " No",
|
|
28904
|
+
nb: " Nei",
|
|
28905
|
+
nn: " Nei",
|
|
28906
|
+
pl: " Nie",
|
|
28907
|
+
ga: " Níl"
|
|
28908
|
+
},
|
|
28909
|
+
"Segja pass?": {
|
|
28910
|
+
en: "Pass the turn?",
|
|
28911
|
+
nb: "Passere turen?",
|
|
28912
|
+
nn: "Passere turen?",
|
|
28913
|
+
pl: "Spasować kolej?",
|
|
28914
|
+
ga: "Pas an tsealaíocht?"
|
|
28915
|
+
},
|
|
28916
|
+
"2x3 pöss í röð ljúka viðureign": {
|
|
28917
|
+
en: "2x3 passes in a row end the game",
|
|
28918
|
+
nb: "2x3 pasninger på rad avslutter spillet",
|
|
28919
|
+
nn: "2x3 pasningar på rad avsluttar spelet",
|
|
28920
|
+
pl: "2x3 pasy z rzędu kończą grę",
|
|
28921
|
+
ga: "Críochnaíonn 2x3 pasanna as a chéile an cluiche"
|
|
28922
|
+
},
|
|
28923
|
+
"Viðureign lýkur þar með": {
|
|
28924
|
+
en: "This finishes the game",
|
|
28925
|
+
nb: "Dette avslutter spillet",
|
|
28926
|
+
nn: "Dette avsluttar spelet",
|
|
28927
|
+
pl: "To kończy grę",
|
|
28928
|
+
ga: "Críochnaíonn sé seo an cluiche"
|
|
28929
|
+
},
|
|
28930
|
+
Skipta: Skipta,
|
|
28931
|
+
"Smelltu á flísarnar sem þú vilt skipta": {
|
|
28932
|
+
en: "Click on the tiles that you wish to exchange",
|
|
28933
|
+
nb: "Klikk på brikkene du ønsker å bytte",
|
|
28934
|
+
nn: "Klikk på brikkene du ønskjer å byte",
|
|
28935
|
+
pl: "Kliknij na kafelki, które chcesz wymienić",
|
|
28936
|
+
ga: "Cliceáil ar na tíleanna ar mhaith leat a mhalartú"
|
|
28937
|
+
},
|
|
28938
|
+
"Véfengja lögn?": {
|
|
28939
|
+
en: "Challenge move?",
|
|
28940
|
+
nb: "Utfordre trekk?",
|
|
28941
|
+
nn: "Utfordre trekk?",
|
|
28942
|
+
pl: "Wyzwanie ruchu?",
|
|
28943
|
+
ga: "Dúshlán bogadh?"
|
|
28944
|
+
},
|
|
28945
|
+
"Röng véfenging kostar 10 stig": {
|
|
28946
|
+
en: "Wrong challenge costs 10 points",
|
|
28947
|
+
nb: "Feil utfordring koster 10 poeng",
|
|
28948
|
+
nn: "Feil utfordring kostar 10 poeng",
|
|
28949
|
+
pl: "Błędne wyzwanie kosztuje 10 punktów",
|
|
28950
|
+
ga: "Cosnaíonn dúshlán mícheart 10 bpointe"
|
|
28951
|
+
},
|
|
28952
|
+
"Er álínis": {
|
|
28953
|
+
en: "Is online",
|
|
28954
|
+
nb: "Er pålogget",
|
|
28955
|
+
nn: "Er pålogga",
|
|
28956
|
+
pl: "Jest online",
|
|
28957
|
+
ga: "Ar líne"
|
|
28958
|
+
},
|
|
28959
|
+
"Álínis?": {
|
|
28960
|
+
en: "Online?",
|
|
28961
|
+
nb: "Pålogget?",
|
|
28962
|
+
nn: "Pålogga?",
|
|
28963
|
+
pl: "Online?",
|
|
28964
|
+
ga: "Ar líne?"
|
|
28965
|
+
},
|
|
28966
|
+
"Röð": {
|
|
28967
|
+
en: "Rank",
|
|
28968
|
+
nb: "Rangering",
|
|
28969
|
+
nn: "Rangering",
|
|
28970
|
+
pl: "Ranking",
|
|
28971
|
+
ga: "Rang"
|
|
28972
|
+
},
|
|
28973
|
+
"Röð í gær": {
|
|
28974
|
+
en: "Rank yesterday",
|
|
28975
|
+
nb: "Rangering i går",
|
|
28976
|
+
nn: "Rangering i går",
|
|
28977
|
+
pl: "Ranking wczoraj",
|
|
28978
|
+
ga: "Rang inné"
|
|
28979
|
+
},
|
|
28980
|
+
"Röð fyrir viku": {
|
|
28981
|
+
en: "Rank a week ago",
|
|
28982
|
+
nb: "Rangering for en uke siden",
|
|
28983
|
+
nn: "Rangering for ei veke sidan",
|
|
28984
|
+
pl: "Ranking tydzień temu",
|
|
28985
|
+
ga: "Rang seachtain ó shin"
|
|
28986
|
+
},
|
|
28987
|
+
"1d": {
|
|
28988
|
+
en: "1d",
|
|
28989
|
+
nb: "1d",
|
|
28990
|
+
nn: "1d",
|
|
28991
|
+
pl: "1d",
|
|
28992
|
+
ga: "1l"
|
|
28993
|
+
},
|
|
28994
|
+
"7d": {
|
|
28995
|
+
en: "7d",
|
|
28996
|
+
nb: "7d",
|
|
28997
|
+
nn: "7d",
|
|
28998
|
+
pl: "7d",
|
|
28999
|
+
ga: "7l"
|
|
29000
|
+
},
|
|
29001
|
+
"30d": {
|
|
29002
|
+
en: "30d",
|
|
29003
|
+
nb: "30d",
|
|
29004
|
+
nn: "30d",
|
|
29005
|
+
pl: "30d",
|
|
29006
|
+
ga: "30l"
|
|
29007
|
+
},
|
|
29008
|
+
"Elo-stig": {
|
|
29009
|
+
en: "Elo points",
|
|
29010
|
+
nb: "Elo-poeng",
|
|
29011
|
+
nn: "Elo-poeng",
|
|
29012
|
+
pl: "Punkty Elo",
|
|
29013
|
+
ga: "Pointí Elo"
|
|
29014
|
+
},
|
|
29015
|
+
"Elo-stig í gær": {
|
|
29016
|
+
en: "Elo points yesterday",
|
|
29017
|
+
nb: "Elo-poeng i går",
|
|
29018
|
+
nn: "Elo-poeng i går",
|
|
29019
|
+
pl: "Punkty Elo wczoraj",
|
|
29020
|
+
ga: "Pointí Elo inné"
|
|
29021
|
+
},
|
|
29022
|
+
"Elo-stig fyrir viku": {
|
|
29023
|
+
en: "Elo points a week ago",
|
|
29024
|
+
nb: "Elo-poeng for en uke siden",
|
|
29025
|
+
nn: "Elo-poeng for ei veke sidan",
|
|
29026
|
+
pl: "Punkty Elo tydzień temu",
|
|
29027
|
+
ga: "Pointí Elo seachtain ó shin"
|
|
29028
|
+
},
|
|
29029
|
+
"Elo-stig fyrir mánuði": {
|
|
29030
|
+
en: "Elo points a month ago",
|
|
29031
|
+
nb: "Elo-poeng for en måned siden",
|
|
29032
|
+
nn: "Elo-poeng for ein månad sidan",
|
|
29033
|
+
pl: "Punkty Elo miesiąc temu",
|
|
29034
|
+
ga: "Pointí Elo mí ó shin"
|
|
29035
|
+
},
|
|
29036
|
+
elo_list_choice: elo_list_choice,
|
|
29037
|
+
stats_choice: stats_choice,
|
|
29038
|
+
"Fjöldi viðureigna": {
|
|
29039
|
+
en: "Number of games",
|
|
29040
|
+
nb: "Antall spill",
|
|
29041
|
+
nn: "Tal på spel",
|
|
29042
|
+
pl: "Liczba gier",
|
|
29043
|
+
ga: "Líon cluichí"
|
|
29044
|
+
},
|
|
29045
|
+
Vinningshlutfall: Vinningshlutfall,
|
|
29046
|
+
"Meðalstigafjöldi": {
|
|
29047
|
+
en: "Average score",
|
|
29048
|
+
nb: "Gjennomsnittlig poengsum",
|
|
29049
|
+
nn: "Gjennomsnittleg poengsum",
|
|
29050
|
+
pl: "Średni wynik",
|
|
29051
|
+
ga: "Scór meánach"
|
|
29052
|
+
},
|
|
29053
|
+
" gegn öllum ": {
|
|
29054
|
+
en: " against all ",
|
|
29055
|
+
nb: " mot alle ",
|
|
29056
|
+
nn: " mot alle ",
|
|
29057
|
+
pl: " przeciwko wszystkim ",
|
|
29058
|
+
ga: " in aghaidh gach "
|
|
29059
|
+
},
|
|
29060
|
+
" gegn þér ": {
|
|
29061
|
+
en: " against you ",
|
|
29062
|
+
nb: " mot deg ",
|
|
29063
|
+
nn: " mot deg ",
|
|
29064
|
+
pl: " przeciwko tobie ",
|
|
29065
|
+
ga: " in aghaidh tú "
|
|
29066
|
+
},
|
|
29067
|
+
" - veldu lengd viðureignar:": {
|
|
29068
|
+
en: " - choose game duration:",
|
|
29069
|
+
nb: " - velg spillvarighet:",
|
|
29070
|
+
nn: " - vel spelvarigheit:",
|
|
29071
|
+
pl: " - wybierz czas trwania gry:",
|
|
29072
|
+
ga: " - roghnaigh fad an chluiche:"
|
|
29073
|
+
},
|
|
29074
|
+
"2 x 10 mínútur": {
|
|
29075
|
+
en: "2 x 10 minutes",
|
|
29076
|
+
nb: "2 x 10 minutter",
|
|
29077
|
+
nn: "2 x 10 minutt",
|
|
29078
|
+
pl: "2 x 10 minut",
|
|
29079
|
+
ga: "2 x 10 nóiméad"
|
|
29080
|
+
},
|
|
29081
|
+
"2 x 15 mínútur": {
|
|
29082
|
+
en: "2 x 15 minutes",
|
|
29083
|
+
nb: "2 x 15 minutter",
|
|
29084
|
+
nn: "2 x 15 minutt",
|
|
29085
|
+
pl: "2 x 15 minut",
|
|
29086
|
+
ga: "2 x 15 nóiméad"
|
|
29087
|
+
},
|
|
29088
|
+
"2 x 20 mínútur": {
|
|
29089
|
+
en: "2 x 20 minutes",
|
|
29090
|
+
nb: "2 x 20 minutter",
|
|
29091
|
+
nn: "2 x 20 minutt",
|
|
29092
|
+
pl: "2 x 20 minut",
|
|
29093
|
+
ga: "2 x 20 nóiméad"
|
|
29094
|
+
},
|
|
29095
|
+
"2 x 25 mínútur": {
|
|
29096
|
+
en: "2 x 25 minutes",
|
|
29097
|
+
nb: "2 x 25 minutter",
|
|
29098
|
+
nn: "2 x 25 minutt",
|
|
29099
|
+
pl: "2 x 25 minut",
|
|
29100
|
+
ga: "2 x 25 nóiméad"
|
|
29101
|
+
},
|
|
29102
|
+
"2 x 30 mínútur": {
|
|
29103
|
+
en: "2 x 30 minutes",
|
|
29104
|
+
nb: "2 x 30 minutter",
|
|
29105
|
+
nn: "2 x 30 minutt",
|
|
29106
|
+
pl: "2 x 30 minut",
|
|
29107
|
+
ga: "2 x 30 nóiméad"
|
|
29108
|
+
},
|
|
29109
|
+
"Báðir leikmenn lýsa því yfir að þeir skrafla ": {
|
|
29110
|
+
en: "Both players declare that they play ",
|
|
29111
|
+
nb: "Begge spillere erklærer at de spiller ",
|
|
29112
|
+
nn: "Begge spelarar erklærer at dei spelar ",
|
|
29113
|
+
pl: "Obaj gracze deklarują, że grają ",
|
|
29114
|
+
ga: "Dearbhaíonn an bheirt imreoirí go n-imríonn siad "
|
|
29115
|
+
},
|
|
29116
|
+
"Flísar sem eftir eru": {
|
|
29117
|
+
en: "Tiles remaining",
|
|
29118
|
+
nb: "Fliser igjen",
|
|
29119
|
+
nn: "Fliser igjen",
|
|
29120
|
+
pl: "Pozostałe kafelki",
|
|
29121
|
+
ga: "Tíleanna fágtha"
|
|
29122
|
+
},
|
|
29123
|
+
"Hvaða staf táknar auða flísin?": {
|
|
29124
|
+
en: "Which letter does the blank tile represent?",
|
|
29125
|
+
nb: "Hvilken bokstav representerer den blanke flisen?",
|
|
29126
|
+
nn: "Kva bokstav representerer den blanke flisa?",
|
|
29127
|
+
pl: "Jaką literę reprezentuje pusty kafelek?",
|
|
29128
|
+
ga: "Cén litir a léiríonn an tíl bán?"
|
|
29129
|
+
},
|
|
29130
|
+
"Þvinga til uppgjafar": {
|
|
29131
|
+
en: "Force to resign",
|
|
29132
|
+
nb: "Tving til å gi opp",
|
|
29133
|
+
nn: "Tving til å gje opp",
|
|
29134
|
+
pl: "Zmusić do rezygnacji",
|
|
29135
|
+
ga: "Éignigh le héirí as"
|
|
29136
|
+
},
|
|
29137
|
+
"14 dagar liðnir án leiks": {
|
|
29138
|
+
en: "14 days elapsed without a move",
|
|
29139
|
+
nb: "14 dager gått uten trekk",
|
|
29140
|
+
nn: "14 dagar gått utan trekk",
|
|
29141
|
+
pl: "Upłynęło 14 dni bez ruchu",
|
|
29142
|
+
ga: "14 lá caite gan bogadh"
|
|
29143
|
+
},
|
|
29144
|
+
"Gefa viðureign": {
|
|
29145
|
+
en: "Resign from game",
|
|
29146
|
+
nb: "Gi opp spillet",
|
|
29147
|
+
nn: "Gje opp spelet",
|
|
29148
|
+
pl: "Zrezygnować z gry",
|
|
29149
|
+
ga: "Éirigh as an gcluiche"
|
|
29150
|
+
},
|
|
29151
|
+
"Skipta stöfum": {
|
|
29152
|
+
en: "Exchange tiles",
|
|
29153
|
+
nb: "Bytt fliser",
|
|
29154
|
+
nn: "Byt fliser",
|
|
29155
|
+
pl: "Wymień kafelki",
|
|
29156
|
+
ga: "Malartú tíleanna"
|
|
29157
|
+
},
|
|
29158
|
+
word_not_found: word_not_found,
|
|
29159
|
+
"Smelltu til að fletta upp": {
|
|
29160
|
+
en: "Click to look up",
|
|
29161
|
+
nb: "Klikk for å slå opp",
|
|
29162
|
+
nn: "Klikk for å slå opp",
|
|
29163
|
+
pl: "Kliknij, aby wyszukać",
|
|
29164
|
+
ga: "Cliceáil chun cuardach"
|
|
29165
|
+
},
|
|
29166
|
+
"Skoða yfirlit": {
|
|
29167
|
+
en: "Review game",
|
|
29168
|
+
nb: "Gjennomgå spill",
|
|
29169
|
+
nn: "Gjennomgå spel",
|
|
29170
|
+
pl: "Przejrzyj grę",
|
|
29171
|
+
ga: "Athbhreithniú cluiche"
|
|
29172
|
+
},
|
|
29173
|
+
"Skraflað án hjálpartækja": {
|
|
29174
|
+
en: "Game without helpers or tools",
|
|
29175
|
+
nb: "Spill uten hjelpemidler eller verktøy",
|
|
29176
|
+
nn: "Spel utan hjelpemiddel eller verktøy",
|
|
29177
|
+
pl: "Gra bez pomocy lub narzędzi",
|
|
29178
|
+
ga: "Cluiche gan chúntóirí nó uirlisí"
|
|
29179
|
+
},
|
|
29180
|
+
"Skraflar án hjálpartækja": {
|
|
29181
|
+
en: "Plays without helpers or tools",
|
|
29182
|
+
nb: "Spiller uten hjelpemidler eller verktøy",
|
|
29183
|
+
nn: "Spelar utan hjelpemiddel eller verktøy",
|
|
29184
|
+
pl: "Gra bez pomocy lub narzędzi",
|
|
29185
|
+
ga: "Imríonn gan chúntóirí nó uirlisí"
|
|
29186
|
+
},
|
|
29187
|
+
"Til í viðureign með klukku": {
|
|
29188
|
+
en: "Willing to play timed games",
|
|
29189
|
+
nb: "Villig til å spille tidsbegrensede spill",
|
|
29190
|
+
nn: "Villig til å spele tidsbegrensa spel",
|
|
29191
|
+
pl: "Chętny do gry w gry zegarowe",
|
|
29192
|
+
ga: "Toilteanach cluichí ama a imirt"
|
|
29193
|
+
},
|
|
29194
|
+
"Álínis og tekur við áskorunum": {
|
|
29195
|
+
en: "Online and accepting challenges",
|
|
29196
|
+
nb: "Pålogget og aksepterer utfordringer",
|
|
29197
|
+
nn: "Pålogga og aksepterer utfordringar",
|
|
29198
|
+
pl: "Online i akceptuje wyzwania",
|
|
29199
|
+
ga: "Ar líne agus ag glacadh le dúshláin"
|
|
29200
|
+
},
|
|
29201
|
+
"Enginn stafur lagður niður": {
|
|
29202
|
+
en: "No tile played",
|
|
29203
|
+
nb: "Ingen flis spilt",
|
|
29204
|
+
nn: "Inga flis spelt",
|
|
29205
|
+
pl: "Żaden kafelek nie został położony",
|
|
29206
|
+
ga: "Níor imríodh aon tíl"
|
|
29207
|
+
},
|
|
29208
|
+
"Fyrsta orð verður að liggja um byrjunarreitinn": {
|
|
29209
|
+
en: "First word must cover the start square",
|
|
29210
|
+
nb: "Første ord må dekke startfeltet",
|
|
29211
|
+
nn: "Første ord må dekkje startfeltet",
|
|
29212
|
+
pl: "Pierwsze słowo musi pokryć pole startowe",
|
|
29213
|
+
ga: "Caithfidh an chéad fhocal an cearnóg tosaigh a chlúdach"
|
|
29214
|
+
},
|
|
29215
|
+
"Orð verður að vera samfellt á borðinu": {
|
|
29216
|
+
en: "Word must be placed consecutively on the board",
|
|
29217
|
+
nb: "Ord må plasseres etter hverandre på brettet",
|
|
29218
|
+
nn: "Ord må plasserast etter kvarandre på brettet",
|
|
29219
|
+
pl: "Słowo musi być umieszczone kolejno na planszy",
|
|
29220
|
+
ga: "Caithfear an focal a chur go leanúnach ar an mbord"
|
|
29221
|
+
},
|
|
29222
|
+
"Orð verður að tengjast orði sem fyrir er": {
|
|
29223
|
+
en: "Word must be connected to another word on the board",
|
|
29224
|
+
nb: "Ord må være koblet til et annet ord på brettet",
|
|
29225
|
+
nn: "Ord må vere kopla til eit anna ord på brettet",
|
|
29226
|
+
pl: "Słowo musi być połączone z innym słowem na planszy",
|
|
29227
|
+
ga: "Caithfidh an focal a bheith ceangailte le focal eile ar an mbord"
|
|
29228
|
+
},
|
|
29229
|
+
"Reitur þegar upptekinn": {
|
|
29230
|
+
en: "Square is already occupied",
|
|
29231
|
+
nb: "Feltet er allerede opptatt",
|
|
29232
|
+
nn: "Feltet er allereie oppteke",
|
|
29233
|
+
pl: "Pole jest już zajęte",
|
|
29234
|
+
ga: "Tá an cearnóg áitithe cheana"
|
|
29235
|
+
},
|
|
29236
|
+
"Ekki má vera eyða í orði": {
|
|
29237
|
+
en: "Word cannot contain a space",
|
|
29238
|
+
nb: "Ord kan ikke inneholde et mellomrom",
|
|
29239
|
+
nn: "Ord kan ikkje innehalde eit mellomrom",
|
|
29240
|
+
pl: "Słowo nie może zawierać spacji",
|
|
29241
|
+
ga: "Ní féidir spás a bheith i bhfocal"
|
|
29242
|
+
},
|
|
29243
|
+
"Of margir stafir lagðir niður": {
|
|
29244
|
+
en: "Too many tiles laid down",
|
|
29245
|
+
nb: "For mange fliser lagt ned",
|
|
29246
|
+
nn: "For mange fliser lagde ned",
|
|
29247
|
+
pl: "Położono zbyt wiele kafelków",
|
|
29248
|
+
ga: "Leagadh síos an iomarca tíleanna"
|
|
29249
|
+
},
|
|
29250
|
+
"Stafur er ekki í rekkanum": {
|
|
29251
|
+
en: "Tile is not present in the player's rack",
|
|
29252
|
+
nb: "Flisen er ikke til stede i spillerens stativ",
|
|
29253
|
+
nn: "Flisa er ikkje til stades i spelaren sitt stativ",
|
|
29254
|
+
pl: "Kafelek nie znajduje się na stojaku gracza",
|
|
29255
|
+
ga: "Níl an tíl i raca an imreora"
|
|
29256
|
+
},
|
|
29257
|
+
"Of fáir stafir eftir, skipting ekki leyfð": {
|
|
29258
|
+
en: "Too few tiles left in bag; exchange not permitted",
|
|
29259
|
+
nb: "For få fliser igjen i posen; bytte ikke tillatt",
|
|
29260
|
+
nn: "For få fliser igjen i posen; byte ikkje tillate",
|
|
29261
|
+
pl: "Zbyt mało kafelków w worku; wymiana niedozwolona",
|
|
29262
|
+
ga: "Ró-bheag tíleanna fágtha sa mhála; malartú toirmiscthe"
|
|
29263
|
+
},
|
|
29264
|
+
"Of mörgum stöfum skipt": {
|
|
29265
|
+
en: "Too many tiles exchanged",
|
|
29266
|
+
nb: "For mange fliser byttet",
|
|
29267
|
+
nn: "For mange fliser bytte",
|
|
29268
|
+
pl: "Wymieniono zbyt wiele kafelków",
|
|
29269
|
+
ga: "Malartaíodh an iomarca tíleanna"
|
|
29270
|
+
},
|
|
29271
|
+
"Leik vantar á borðið - endurglæðið vefráparann": {
|
|
29272
|
+
en: "Move missing from board - refresh browser",
|
|
29273
|
+
nb: "Trekk mangler på brettet - oppdater nettleseren",
|
|
29274
|
+
nn: "Trekk manglar på brettet - oppdater nettlesaren",
|
|
29275
|
+
pl: "Ruch nieobecny na planszy - odśwież przeglądarkę",
|
|
29276
|
+
ga: "Bogadh in easnamh ón mbord - athnuaigh an brabhsálaí"
|
|
29277
|
+
},
|
|
29278
|
+
"Notandi ekki innskráður - endurglæðið vefráparann": {
|
|
29279
|
+
en: "User not logged in - refresh browser",
|
|
29280
|
+
nb: "Bruker ikke logget inn - oppdater nettleseren",
|
|
29281
|
+
nn: "Brukar ikkje logga inn - oppdater nettlesaren",
|
|
29282
|
+
pl: "Użytkownik nie jest zalogowany - odśwież przeglądarkę",
|
|
29283
|
+
ga: "Úsáideoir gan logáil isteach - athnuaigh an brabhsálaí"
|
|
29284
|
+
},
|
|
29285
|
+
"Rangur eða óþekktur notandi": {
|
|
29286
|
+
en: "Wrong or unknown user",
|
|
29287
|
+
nb: "Feil eller ukjent bruker",
|
|
29288
|
+
nn: "Feil eller ukjend brukar",
|
|
29289
|
+
pl: "Błędny lub nieznany użytkownik",
|
|
29290
|
+
ga: "Úsáideoir mícheart nó anaithnid"
|
|
29291
|
+
},
|
|
29292
|
+
"Viðureign finnst ekki": {
|
|
29293
|
+
en: "Game not found",
|
|
29294
|
+
nb: "Spill ikke funnet",
|
|
29295
|
+
nn: "Spel ikkje funne",
|
|
29296
|
+
pl: "Gra nie znaleziona",
|
|
29297
|
+
ga: "Cluiche gan aimsiú"
|
|
29298
|
+
},
|
|
29299
|
+
"Viðureign er ekki utan tímamarka": {
|
|
29300
|
+
en: "Game has not exceeded time limit",
|
|
29301
|
+
nb: "Spillet har ikke overskredet tidsbegrensningen",
|
|
29302
|
+
nn: "Spelet har ikkje overskride tidsbegrensinga",
|
|
29303
|
+
pl: "Gra nie przekroczyła limitu czasu",
|
|
29304
|
+
ga: "Níor sháraigh an cluiche an teorainn ama"
|
|
29305
|
+
},
|
|
29306
|
+
"Netþjónn gat ekki tekið við leiknum - reyndu aftur": {
|
|
29307
|
+
en: "Server is unable to process move - try again",
|
|
29308
|
+
nb: "Serveren kan ikke behandle trekket - prøv igjen",
|
|
29309
|
+
nn: "Tenaren kan ikkje behandle trekket - prøv igjen",
|
|
29310
|
+
pl: "Serwer nie może przetworzyć ruchu - spróbuj ponownie",
|
|
29311
|
+
ga: "Ní féidir leis an bhfreastalaí an gluaiseacht a phróiseáil - bain triail eile as"
|
|
29312
|
+
},
|
|
29313
|
+
"Véfenging er ekki möguleg í þessari viðureign": {
|
|
29314
|
+
en: "A challenge is not possible in this game",
|
|
29315
|
+
nb: "En utfordring er ikke mulig i dette spillet",
|
|
29316
|
+
nn: "Ei utfordring er ikkje mogleg i dette spelet",
|
|
29317
|
+
pl: "Wyzwanie nie jest możliwe w tej grze",
|
|
29318
|
+
ga: "Ní féidir dúshlán a thabhairt sa chluiche seo"
|
|
29319
|
+
},
|
|
29320
|
+
"Síðasti leikur er ekki véfengjanlegur": {
|
|
29321
|
+
en: "The last move cannot be challenged",
|
|
29322
|
+
nb: "Siste trekk kan ikke utfordres",
|
|
29323
|
+
nn: "Siste trekk kan ikkje utfordrast",
|
|
29324
|
+
pl: "Ostatniego ruchu nie można zakwestionować",
|
|
29325
|
+
ga: "Ní féidir an gluaiseacht deireanach a dhúshlánú"
|
|
29326
|
+
},
|
|
29327
|
+
"Aðeins véfenging eða pass leyfileg": {
|
|
29328
|
+
en: "Only a challenge or a pass are possible",
|
|
29329
|
+
nb: "Bare en utfordring eller pass er mulig",
|
|
29330
|
+
nn: "Berre ei utfordring eller pass er mogleg",
|
|
29331
|
+
pl: "Możliwe jest tylko wyzwanie lub pas",
|
|
29332
|
+
ga: "Níl ach dúshlán nó pas indéanta"
|
|
29333
|
+
},
|
|
29334
|
+
welcome_2: welcome_2,
|
|
29335
|
+
welcome_1: welcome_1,
|
|
29336
|
+
welcome_0: welcome_0,
|
|
29337
|
+
"Skrái þig inn...": {
|
|
29338
|
+
en: "Logging you in...",
|
|
29339
|
+
nb: "Logger deg inn...",
|
|
29340
|
+
nn: "Loggar deg inn...",
|
|
29341
|
+
pl: "Logowanie...",
|
|
29342
|
+
ga: "Ag logáil isteach tú..."
|
|
29343
|
+
},
|
|
29344
|
+
"Innskrá": {
|
|
29345
|
+
en: "Log in",
|
|
29346
|
+
nb: "Logg inn",
|
|
29347
|
+
nn: "Logg inn",
|
|
29348
|
+
pl: "Zaloguj się",
|
|
29349
|
+
ga: "Logáil isteach"
|
|
29350
|
+
},
|
|
29351
|
+
"Smelltu til að raða eftir seinni staf": {
|
|
29352
|
+
en: "Click to sort by last letter",
|
|
29353
|
+
nb: "Klikk for å sortere etter siste bokstav",
|
|
29354
|
+
nn: "Klikk for å sortere etter siste bokstav",
|
|
29355
|
+
pl: "Kliknij, aby posortować według ostatniej litery",
|
|
29356
|
+
ga: "Cliceáil chun sórtáil de réir an litir deireanaigh"
|
|
29357
|
+
},
|
|
29358
|
+
"Smelltu til að raða eftir fyrri staf": {
|
|
29359
|
+
en: "Click to sort by first letter",
|
|
29360
|
+
nb: "Klikk for å sortere etter første bokstav",
|
|
29361
|
+
nn: "Klikk for å sortere etter første bokstav",
|
|
29362
|
+
pl: "Kliknij, aby posortować według pierwszej litery",
|
|
29363
|
+
ga: "Cliceáil chun sórtáil de réir an chéad litir"
|
|
29364
|
+
},
|
|
29365
|
+
"Hvernig reitirnir margfalda stigin": {
|
|
29366
|
+
en: "How squares multiply points",
|
|
29367
|
+
nb: "Hvordan ruter multipliserer poeng",
|
|
29368
|
+
nn: "Korleis ruter multipliserer poeng",
|
|
29369
|
+
pl: "Jak kwadraty mnożą punkty",
|
|
29370
|
+
ga: "Conas a iolraíonn cearnóga pointí"
|
|
29371
|
+
},
|
|
29372
|
+
"Loka þessari hjálp": {
|
|
29373
|
+
en: "Close this help",
|
|
29374
|
+
nb: "Lukk denne hjelpen",
|
|
29375
|
+
nn: "Lukk denne hjelpa",
|
|
29376
|
+
pl: "Zamknij tę pomoc",
|
|
29377
|
+
ga: "Dún an chabhair seo"
|
|
29378
|
+
},
|
|
29379
|
+
"Stokka upp rekka": {
|
|
29380
|
+
en: "Shuffle rack",
|
|
29381
|
+
nb: "Stokk stativet",
|
|
29382
|
+
nn: "Stokk stativet",
|
|
29383
|
+
pl: "Przetasuj stojak",
|
|
29384
|
+
ga: "Measc raca"
|
|
29385
|
+
},
|
|
29386
|
+
"Færa stafi aftur í rekka": {
|
|
29387
|
+
en: "Recall tiles into rack",
|
|
29388
|
+
nb: "Hent fliser tilbake til stativet",
|
|
29389
|
+
nn: "Hent fliser tilbake til stativet",
|
|
29390
|
+
pl: "Przywróć kafelki do stojaka",
|
|
29391
|
+
ga: "Cuimhnigh tíleanna isteach sa raca"
|
|
29392
|
+
},
|
|
29393
|
+
"Besta mögulega lögn": {
|
|
29394
|
+
en: "Best possible move",
|
|
29395
|
+
nb: "Beste mulige trekk",
|
|
29396
|
+
nn: "Beste mogelege trekk",
|
|
29397
|
+
pl: "Najlepszy możliwy ruch",
|
|
29398
|
+
ga: "An bogadh is fearr is féidir"
|
|
29399
|
+
},
|
|
29400
|
+
"Nei, takk": {
|
|
29401
|
+
en: "No, thanks",
|
|
29402
|
+
nb: "Nei, takk",
|
|
29403
|
+
nn: "Nei, takk",
|
|
29404
|
+
pl: "Nie, dziękuję",
|
|
29405
|
+
ga: "Ní hea"
|
|
29406
|
+
},
|
|
29407
|
+
"Fyrri dagur": {
|
|
29408
|
+
en: "Previous day",
|
|
29409
|
+
nb: "Forrige dag",
|
|
29410
|
+
nn: "Førre dag",
|
|
29411
|
+
pl: "Poprzedni dzień",
|
|
29412
|
+
ga: "An lá roimhe"
|
|
29413
|
+
},
|
|
29414
|
+
"Næsti dagur": {
|
|
29415
|
+
en: "Next day",
|
|
29416
|
+
nb: "Neste dag",
|
|
29417
|
+
nn: "Neste dag",
|
|
29418
|
+
pl: "Następny dzień",
|
|
29419
|
+
ga: "An lá dar gcionn"
|
|
29420
|
+
},
|
|
29421
|
+
"Frammistaða": {
|
|
29422
|
+
en: "Performance",
|
|
29423
|
+
nb: "Ytelse",
|
|
29424
|
+
nn: "Yting",
|
|
29425
|
+
pl: "Wyniki",
|
|
29426
|
+
ga: "Feidhmíocht"
|
|
29427
|
+
},
|
|
29428
|
+
"Tölfræði": {
|
|
29429
|
+
en: "Statistics",
|
|
29430
|
+
nb: "Statistikk",
|
|
29431
|
+
nn: "Statistikk",
|
|
29432
|
+
pl: "Statystyki",
|
|
29433
|
+
ga: "Staitisticí"
|
|
29434
|
+
},
|
|
29435
|
+
Stigatafla: Stigatafla,
|
|
29436
|
+
"Tölfræði og stigatafla": {
|
|
29437
|
+
en: "Stats and leaderboard",
|
|
29438
|
+
nb: "Statistikk og toppliste",
|
|
29439
|
+
nn: "Statistikk og toppliste",
|
|
29440
|
+
pl: "Statystyki i tabela",
|
|
29441
|
+
ga: "Staitisticí agus clár"
|
|
29442
|
+
},
|
|
29443
|
+
"Þín besta": {
|
|
29444
|
+
en: "Your best",
|
|
29445
|
+
nb: "Din beste",
|
|
29446
|
+
nn: "Di beste",
|
|
29447
|
+
pl: "Twój najlepszy",
|
|
29448
|
+
ga: "Do cheann is fearr"
|
|
29449
|
+
},
|
|
29450
|
+
"Þú leiðir!": {
|
|
29451
|
+
en: "You lead!",
|
|
29452
|
+
nb: "Du leder!",
|
|
29453
|
+
nn: "Du leier!",
|
|
29454
|
+
pl: "Prowadzisz!",
|
|
29455
|
+
ga: "Tá tú chun tosaigh!"
|
|
29456
|
+
},
|
|
29457
|
+
"Best til þessa": {
|
|
29458
|
+
en: "Best so far",
|
|
29459
|
+
nb: "Beste hittil",
|
|
29460
|
+
nn: "Beste hittil",
|
|
29461
|
+
pl: "Najlepszy dotąd",
|
|
29462
|
+
ga: "Is fearr go dtí seo"
|
|
29463
|
+
},
|
|
29464
|
+
"Sýna besta leik": {
|
|
29465
|
+
en: "Show best move",
|
|
29466
|
+
nb: "Vis beste trekk",
|
|
29467
|
+
nn: "Vis beste trekk",
|
|
29468
|
+
pl: "Pokaż najlepszy ruch",
|
|
29469
|
+
ga: "Taispeáin an bogadh is fearr"
|
|
29470
|
+
},
|
|
29471
|
+
"Sýna leik": {
|
|
29472
|
+
en: "Show move",
|
|
29473
|
+
nb: "Vis trekk",
|
|
29474
|
+
nn: "Vis trekk",
|
|
29475
|
+
pl: "Pokaż ruch",
|
|
29476
|
+
ga: "Taispeáin bogadh"
|
|
29477
|
+
},
|
|
29478
|
+
"Smelltu til að sjá lausn": {
|
|
29479
|
+
en: "Click to see solution",
|
|
29480
|
+
nb: "Klikk for å se løsning",
|
|
29481
|
+
nn: "Klikk for å sjå løysing",
|
|
29482
|
+
pl: "Kliknij, aby zobaczyć rozwiązanie",
|
|
29483
|
+
ga: "Cliceáil chun an réiteach a fheiceáil"
|
|
29484
|
+
},
|
|
29485
|
+
"Þú": {
|
|
29486
|
+
en: "You",
|
|
29487
|
+
nb: "Du",
|
|
29488
|
+
nn: "Du",
|
|
29489
|
+
pl: "Ty",
|
|
29490
|
+
ga: "Tú"
|
|
29491
|
+
},
|
|
29492
|
+
"Sæki tölfræði...": {
|
|
29493
|
+
en: "Loading stats...",
|
|
29494
|
+
nb: "Laster statistikk...",
|
|
29495
|
+
nn: "Lastar statistikk...",
|
|
29496
|
+
pl: "Ładowanie statystyk...",
|
|
29497
|
+
ga: "Ag lódáil staitisticí..."
|
|
29498
|
+
},
|
|
29499
|
+
"Engin tölfræði til að sýna": {
|
|
29500
|
+
en: "No statistics to show",
|
|
29501
|
+
nb: "Ingen statistikk å vise",
|
|
29502
|
+
nn: "Ingen statistikk å vise",
|
|
29503
|
+
pl: "Brak statystyk do wyświetlenia",
|
|
29504
|
+
ga: "Níl aon staitisticí le taispeáint"
|
|
29505
|
+
},
|
|
29506
|
+
"Núverandi striklota": {
|
|
29507
|
+
en: "Current streak",
|
|
29508
|
+
nb: "Nåværende rekke",
|
|
29509
|
+
nn: "Noverande rekkje",
|
|
29510
|
+
pl: "Bieżąca seria",
|
|
29511
|
+
ga: "Sraith reatha"
|
|
29512
|
+
},
|
|
29513
|
+
"Lengsta striklota": {
|
|
29514
|
+
en: "Longest streak",
|
|
29515
|
+
nb: "Lengste rekke",
|
|
29516
|
+
nn: "Lengste rekkje",
|
|
29517
|
+
pl: "Najdłuższa seria",
|
|
29518
|
+
ga: "An tsraith is faide"
|
|
29519
|
+
},
|
|
29520
|
+
"Hæsta skori náð": {
|
|
29521
|
+
en: "Best score achieved",
|
|
29522
|
+
nb: "Beste oppnådde poengsum",
|
|
29523
|
+
nn: "Beste oppnådde poengsum",
|
|
29524
|
+
pl: "Najwyższy wynik",
|
|
29525
|
+
ga: "An scór is fearr"
|
|
29526
|
+
},
|
|
29527
|
+
"Striklota hæsta skors": {
|
|
29528
|
+
en: "Best score streak",
|
|
29529
|
+
nb: "Rekke med beste poengsum",
|
|
29530
|
+
nn: "Rekkje med beste poengsum",
|
|
29531
|
+
pl: "Seria najwyższych wyników",
|
|
29532
|
+
ga: "Sraith scór is fearr"
|
|
29533
|
+
},
|
|
29534
|
+
"Heildarfjöldi daga": {
|
|
29535
|
+
en: "Total days played",
|
|
29536
|
+
nb: "Totalt antall dager",
|
|
29537
|
+
nn: "Totalt tal på dagar",
|
|
29538
|
+
pl: "Łączna liczba dni",
|
|
29539
|
+
ga: "Iomlán laethanta"
|
|
29540
|
+
},
|
|
29541
|
+
"Hleð stigatöflu...": {
|
|
29542
|
+
en: "Loading leaderboard...",
|
|
29543
|
+
nb: "Laster toppliste...",
|
|
29544
|
+
nn: "Lastar toppliste...",
|
|
29545
|
+
pl: "Ładowanie tabeli...",
|
|
29546
|
+
ga: "Ag lódáil an chláir..."
|
|
29547
|
+
},
|
|
29548
|
+
"Engin stig skráð enn": {
|
|
29549
|
+
en: "No scores yet",
|
|
29550
|
+
nb: "Ingen poeng ennå",
|
|
29551
|
+
nn: "Ingen poeng enno",
|
|
29552
|
+
pl: "Brak wyników",
|
|
29553
|
+
ga: "Gan scóir fós"
|
|
29554
|
+
},
|
|
29555
|
+
"Reyna síðar": {
|
|
29556
|
+
en: "Try later",
|
|
29557
|
+
nb: "Prøv senere",
|
|
29558
|
+
nn: "Prøv seinare",
|
|
29559
|
+
pl: "Spróbuj później",
|
|
29560
|
+
ga: "Bain triail níos déanaí"
|
|
29561
|
+
},
|
|
29562
|
+
" mínútur.": {
|
|
29563
|
+
en: " minutes.",
|
|
29564
|
+
nb: " minutter.",
|
|
29565
|
+
nn: " minutt.",
|
|
29566
|
+
pl: " minut.",
|
|
29567
|
+
ga: " nóiméad."
|
|
29568
|
+
},
|
|
29569
|
+
date_format: date_format,
|
|
29570
|
+
january: january,
|
|
29571
|
+
february: february,
|
|
29572
|
+
march: march,
|
|
29573
|
+
april: april,
|
|
29574
|
+
may: may,
|
|
29575
|
+
june: june,
|
|
29576
|
+
july: july,
|
|
29577
|
+
august: august,
|
|
29578
|
+
september: september,
|
|
29579
|
+
october: october,
|
|
29580
|
+
november: november,
|
|
29581
|
+
december: december,
|
|
29582
|
+
"[sentinel]": {
|
|
29583
|
+
}
|
|
29584
|
+
};
|
|
29585
|
+
|
|
27641
29586
|
/*
|
|
27642
29587
|
|
|
27643
|
-
|
|
29588
|
+
i18n.ts
|
|
27644
29589
|
|
|
27645
|
-
|
|
29590
|
+
Single page UI for Netskrafl/Explo using the Mithril library
|
|
27646
29591
|
|
|
27647
29592
|
Copyright (C) 2025 Miðeind ehf.
|
|
27648
|
-
Author:
|
|
29593
|
+
Author: Vilhjálmur Þorsteinsson
|
|
27649
29594
|
|
|
27650
29595
|
The Creative Commons Attribution-NonCommercial 4.0
|
|
27651
29596
|
International Public License (CC-BY-NC 4.0) applies to this software.
|
|
27652
29597
|
For further information, see https://github.com/mideind/Netskrafl
|
|
27653
29598
|
|
|
29599
|
+
|
|
29600
|
+
This module contains internationalization (i18n) utility functions,
|
|
29601
|
+
allowing for translation of displayed text between languages.
|
|
29602
|
+
|
|
29603
|
+
Text messages are embedded directly from the messages.json file
|
|
29604
|
+
at build time.
|
|
29605
|
+
|
|
27654
29606
|
*/
|
|
27655
|
-
//
|
|
27656
|
-
|
|
27657
|
-
|
|
27658
|
-
|
|
27659
|
-
|
|
27660
|
-
|
|
27661
|
-
const
|
|
27662
|
-
|
|
27663
|
-
|
|
27664
|
-
|
|
27665
|
-
|
|
27666
|
-
|
|
27667
|
-
|
|
27668
|
-
|
|
27669
|
-
|
|
27670
|
-
|
|
27671
|
-
|
|
27672
|
-
|
|
27673
|
-
|
|
27674
|
-
|
|
27675
|
-
|
|
27676
|
-
|
|
27677
|
-
|
|
27678
|
-
|
|
27679
|
-
|
|
27680
|
-
|
|
27681
|
-
|
|
27682
|
-
|
|
27683
|
-
|
|
27684
|
-
|
|
27685
|
-
|
|
27686
|
-
|
|
29607
|
+
// Current exact user locale and fallback locale ("en" for "en_US"/"en_GB"/...)
|
|
29608
|
+
// This is overwritten in setLocale()
|
|
29609
|
+
let currentLocale = 'is_IS';
|
|
29610
|
+
let currentFallback = 'is';
|
|
29611
|
+
// Regex that matches embedded interpolations such as "Welcome, {username}!"
|
|
29612
|
+
// Interpolation identifiers should only contain ASCII characters, digits and '_'
|
|
29613
|
+
const rex = /{\s*(\w+)\s*}/g;
|
|
29614
|
+
let messages = {};
|
|
29615
|
+
let messagesLoaded = false;
|
|
29616
|
+
function getLocaleFromUrl() {
|
|
29617
|
+
// Check for a ?lang= query parameter to override the locale
|
|
29618
|
+
// Accepts formats like: lang=nb, lang=nb-NO, lang=nb_NO
|
|
29619
|
+
const params = new URLSearchParams(window.location.search);
|
|
29620
|
+
const lang = params.get('lang');
|
|
29621
|
+
if (!lang)
|
|
29622
|
+
return null;
|
|
29623
|
+
// Normalize: nb-NO → nb_NO
|
|
29624
|
+
return lang.replace('-', '_');
|
|
29625
|
+
}
|
|
29626
|
+
function hasAnyTranslation(msgs, locale) {
|
|
29627
|
+
// Return true if any translation is available for the given locale
|
|
29628
|
+
for (const key in msgs) {
|
|
29629
|
+
if (msgs[key][locale] !== undefined)
|
|
29630
|
+
return true;
|
|
29631
|
+
}
|
|
29632
|
+
return false;
|
|
29633
|
+
}
|
|
29634
|
+
function setLocale(locale, msgs) {
|
|
29635
|
+
// Set the current i18n locale and fallback
|
|
29636
|
+
currentLocale = locale;
|
|
29637
|
+
currentFallback = locale.split('_')[0];
|
|
29638
|
+
// For unsupported locales, i.e. locales that have no
|
|
29639
|
+
// translations available for them, fall back to English (U.S.).
|
|
29640
|
+
if (!hasAnyTranslation(msgs, currentLocale) &&
|
|
29641
|
+
!hasAnyTranslation(msgs, currentFallback)) {
|
|
29642
|
+
currentLocale = 'en_US';
|
|
29643
|
+
currentFallback = 'en';
|
|
29644
|
+
}
|
|
29645
|
+
// Flatten the Messages structure, enabling long strings
|
|
29646
|
+
// to be represented as string arrays in the messages.json file
|
|
29647
|
+
messages = {};
|
|
29648
|
+
for (const key in msgs) {
|
|
29649
|
+
for (const lc in msgs[key]) {
|
|
29650
|
+
let s = msgs[key][lc];
|
|
29651
|
+
if (Array.isArray(s))
|
|
29652
|
+
s = s.join('');
|
|
29653
|
+
if (messages[key] === undefined)
|
|
29654
|
+
messages[key] = {};
|
|
29655
|
+
// If the string s contains HTML markup of the form <tag>...</tag>,
|
|
29656
|
+
// convert it into a list of Mithril Vnode children corresponding to
|
|
29657
|
+
// the text and the tags
|
|
29658
|
+
if (s.match(/<[a-z]+>/)) {
|
|
29659
|
+
// Looks like the string contains HTML markup
|
|
29660
|
+
const vnodes = [];
|
|
29661
|
+
let i = 0;
|
|
29662
|
+
let tagMatch = null;
|
|
29663
|
+
while (i < s.length &&
|
|
29664
|
+
// biome-ignore lint/suspicious/noAssignInExpressions: Done for efficiency
|
|
29665
|
+
(tagMatch = s.slice(i).match(/<[a-z]+>/)) &&
|
|
29666
|
+
tagMatch.index !== undefined) {
|
|
29667
|
+
// Found what looks like an HTML tag
|
|
29668
|
+
// Calculate the index of the enclosed text within s
|
|
29669
|
+
const tag = tagMatch[0];
|
|
29670
|
+
const j = i + tagMatch.index + tag.length;
|
|
29671
|
+
// Find the end tag
|
|
29672
|
+
const end = s.indexOf(`</${tag.slice(1)}`, j);
|
|
29673
|
+
if (end < 0) {
|
|
29674
|
+
// No end tag - skip past this weirdness
|
|
29675
|
+
i = j;
|
|
29676
|
+
continue;
|
|
29677
|
+
}
|
|
29678
|
+
// Add the text preceding the tag
|
|
29679
|
+
if (tagMatch.index > 0)
|
|
29680
|
+
vnodes.push(s.slice(i, i + tagMatch.index));
|
|
29681
|
+
// Create the Mithril node corresponding to the tag and the enclosed text
|
|
29682
|
+
// and add it to the list
|
|
29683
|
+
vnodes.push(m(tag.slice(1, -1), s.slice(j, end)));
|
|
29684
|
+
// Advance the index past the end of the tag
|
|
29685
|
+
i = end + tag.length + 1;
|
|
29686
|
+
}
|
|
29687
|
+
// Push the final text part, if any
|
|
29688
|
+
if (i < s.length)
|
|
29689
|
+
vnodes.push(s.slice(i));
|
|
29690
|
+
// Reassign s to the list of vnodes
|
|
29691
|
+
s = vnodes;
|
|
29692
|
+
}
|
|
29693
|
+
messages[key][lc] = s;
|
|
29694
|
+
}
|
|
29695
|
+
}
|
|
29696
|
+
messagesLoaded = true;
|
|
29697
|
+
}
|
|
29698
|
+
function initMessages(locale) {
|
|
29699
|
+
// Initialize the i18n messages with the embedded messages data
|
|
29700
|
+
// and set the user's locale. A ?lang= URL parameter overrides the locale.
|
|
29701
|
+
const override = getLocaleFromUrl();
|
|
29702
|
+
setLocale(override || locale, messagesData);
|
|
29703
|
+
}
|
|
29704
|
+
function t(key, ips = {}) {
|
|
29705
|
+
// Main text translation function, supporting interpolation
|
|
29706
|
+
// and HTML tag substitution
|
|
29707
|
+
const msgDict = messages[key];
|
|
29708
|
+
if (msgDict === undefined)
|
|
29709
|
+
// No dictionary for this key - may actually be a missing entry
|
|
29710
|
+
return messagesLoaded ? key : '';
|
|
29711
|
+
// Lookup exact locale, then fallback, then resort to returning the key
|
|
29712
|
+
const message = msgDict[currentLocale] || msgDict[currentFallback] || key;
|
|
29713
|
+
// If we have an interpolation object, do the interpolation first
|
|
29714
|
+
return Object.keys(ips).length ? interpolate(message, ips) : message;
|
|
29715
|
+
}
|
|
29716
|
+
function ts(key, ips = {}) {
|
|
29717
|
+
// String translation function, supporting interpolation
|
|
29718
|
+
// but not HTML tag substitution
|
|
29719
|
+
const msgDict = messages[key];
|
|
29720
|
+
if (msgDict === undefined)
|
|
29721
|
+
// No dictionary for this key - may actually be a missing entry
|
|
29722
|
+
return messagesLoaded ? key : '';
|
|
29723
|
+
// Lookup exact locale, then fallback, then resort to returning the key
|
|
29724
|
+
const message = msgDict[currentLocale] || msgDict[currentFallback] || key;
|
|
29725
|
+
if (typeof message !== 'string')
|
|
29726
|
+
// This is actually an error - the client should be calling t() instead
|
|
29727
|
+
return '';
|
|
29728
|
+
// If we have an interpolation object, do the interpolation first
|
|
29729
|
+
return Object.keys(ips).length ? interpolate_string(message, ips) : message;
|
|
29730
|
+
}
|
|
29731
|
+
function mt(cls, children) {
|
|
29732
|
+
// Wrapper for the Mithril m() function that auto-translates
|
|
29733
|
+
// string and array arguments
|
|
29734
|
+
if (typeof children === 'string') {
|
|
29735
|
+
return m(cls, t(children));
|
|
29736
|
+
}
|
|
29737
|
+
if (Array.isArray(children)) {
|
|
29738
|
+
return m(cls, children.map((item) => (typeof item === 'string' ? t(item) : item)));
|
|
29739
|
+
}
|
|
29740
|
+
return m(cls, children);
|
|
29741
|
+
}
|
|
29742
|
+
function interpolate(message, ips) {
|
|
29743
|
+
// Replace interpolation placeholders with their corresponding values
|
|
29744
|
+
if (typeof message === 'string') {
|
|
29745
|
+
return message.replace(rex, (match, key) => ips[key] || match);
|
|
29746
|
+
}
|
|
29747
|
+
if (Array.isArray(message)) {
|
|
29748
|
+
return message.map((item) => interpolate(item, ips));
|
|
29749
|
+
}
|
|
29750
|
+
return message;
|
|
29751
|
+
}
|
|
29752
|
+
function interpolate_string(message, ips) {
|
|
29753
|
+
// Replace interpolation placeholders with their corresponding values
|
|
29754
|
+
return message.replace(rex, (match, key) => ips[key] || match);
|
|
29755
|
+
}
|
|
27687
29756
|
|
|
27688
29757
|
/*
|
|
27689
29758
|
|
|
@@ -27710,6 +29779,21 @@ var hasZoomed = false;
|
|
|
27710
29779
|
// Old-style (non-single-page) game URL prefix
|
|
27711
29780
|
const BOARD_PREFIX = '/board?game=';
|
|
27712
29781
|
const BOARD_PREFIX_LEN = BOARD_PREFIX.length;
|
|
29782
|
+
// Translation keys for month names (january, february, etc.)
|
|
29783
|
+
const MONTH_KEYS = [
|
|
29784
|
+
'january',
|
|
29785
|
+
'february',
|
|
29786
|
+
'march',
|
|
29787
|
+
'april',
|
|
29788
|
+
'may',
|
|
29789
|
+
'june',
|
|
29790
|
+
'july',
|
|
29791
|
+
'august',
|
|
29792
|
+
'september',
|
|
29793
|
+
'october',
|
|
29794
|
+
'november',
|
|
29795
|
+
'december',
|
|
29796
|
+
];
|
|
27713
29797
|
function addPinchZoom(attrs, funcZoomIn, funcZoomOut) {
|
|
27714
29798
|
// Install event handlers for the pointer target
|
|
27715
29799
|
attrs.onpointerdown = pointerdown_handler;
|
|
@@ -27924,6 +30008,15 @@ function valueOrK(value, breakpoint = 10000) {
|
|
|
27924
30008
|
value = Math.round(value / 1000);
|
|
27925
30009
|
return `${sign}${value}K`;
|
|
27926
30010
|
}
|
|
30011
|
+
function formatDate(dateStr) {
|
|
30012
|
+
// Format YYYY-MM-DD to localized date using the date_format template
|
|
30013
|
+
// e.g., "2. október" in Icelandic, "October 2" in English
|
|
30014
|
+
// Ensure date is parsed as UTC for consistent formatting
|
|
30015
|
+
const date = new Date(`${dateStr}T00:00:00Z`);
|
|
30016
|
+
const day = date.getUTCDate().toString();
|
|
30017
|
+
const month = ts(MONTH_KEYS[date.getUTCMonth()]);
|
|
30018
|
+
return ts('date_format', { day, month });
|
|
30019
|
+
}
|
|
27927
30020
|
|
|
27928
30021
|
/*
|
|
27929
30022
|
|
|
@@ -27943,10 +30036,14 @@ function valueOrK(value, breakpoint = 10000) {
|
|
|
27943
30036
|
*/
|
|
27944
30037
|
class Actions {
|
|
27945
30038
|
constructor(model) {
|
|
30039
|
+
this.riddleLoading = false; // Prevents concurrent loadRiddle calls
|
|
27946
30040
|
this.model = model;
|
|
27947
30041
|
// Media and Firebase listeners will be initialized
|
|
27948
30042
|
// when view is available
|
|
27949
30043
|
}
|
|
30044
|
+
get isRiddleLoading() {
|
|
30045
|
+
return this.riddleLoading;
|
|
30046
|
+
}
|
|
27950
30047
|
onNavigateTo(routeName, params, view) {
|
|
27951
30048
|
// We have navigated to a new route
|
|
27952
30049
|
// If navigating to something other than help,
|
|
@@ -28452,13 +30549,18 @@ class Actions {
|
|
|
28452
30549
|
this.model.leaderboard = [];
|
|
28453
30550
|
}
|
|
28454
30551
|
else {
|
|
28455
|
-
|
|
28456
|
-
const
|
|
30552
|
+
const { riddle } = this.model;
|
|
30553
|
+
const bestPossibleScore = riddle?.bestPossibleScore ?? Number.POSITIVE_INFINITY;
|
|
30554
|
+
// Convert dictionary to array and filter out invalid entries
|
|
30555
|
+
const entries = Object.keys(json)
|
|
30556
|
+
.map((userId) => ({
|
|
28457
30557
|
userId: json[userId].userId || userId,
|
|
28458
30558
|
displayName: json[userId].displayName || '',
|
|
28459
30559
|
score: json[userId].score || 0,
|
|
28460
30560
|
timestamp: json[userId].timestamp || '',
|
|
28461
|
-
}))
|
|
30561
|
+
}))
|
|
30562
|
+
// Filter out invalid entries (score > bestPossibleScore)
|
|
30563
|
+
.filter((entry) => entry.score <= bestPossibleScore);
|
|
28462
30564
|
// Sort by score descending, then by timestamp ascending (earlier first)
|
|
28463
30565
|
entries.sort((a, b) => {
|
|
28464
30566
|
if (b.score !== a.score) {
|
|
@@ -28500,217 +30602,77 @@ class Actions {
|
|
|
28500
30602
|
// This enables clicking on it to see it on the board
|
|
28501
30603
|
if (!moveExists) {
|
|
28502
30604
|
riddle.playerMoves.push({
|
|
28503
|
-
word,
|
|
28504
|
-
score,
|
|
28505
|
-
coord,
|
|
28506
|
-
timestamp,
|
|
28507
|
-
});
|
|
28508
|
-
}
|
|
28509
|
-
m.redraw();
|
|
28510
|
-
}
|
|
28511
|
-
async fetchRiddle(date, locale) {
|
|
28512
|
-
// Create the game via model
|
|
28513
|
-
if (!this.model)
|
|
28514
|
-
throw new Error('Model is not initialized');
|
|
28515
|
-
await this.model.initRiddle(date, locale);
|
|
28516
|
-
// Attach Firebase listeners
|
|
28517
|
-
this.attachListenerToRiddle(date, locale);
|
|
28518
|
-
}
|
|
28519
|
-
cleanupRiddle(date, locale) {
|
|
28520
|
-
// Detach Firebase listeners
|
|
28521
|
-
this.detachListenerFromRiddle(date, locale);
|
|
28522
|
-
}
|
|
28523
|
-
} // class Actions
|
|
28524
|
-
function createRouteResolver(actions, view) {
|
|
28525
|
-
// Return a map of routes to onmatch and render functions
|
|
28526
|
-
const model = actions.model;
|
|
28527
|
-
// let state = model.state;
|
|
28528
|
-
return model.paths.reduce((acc, item) => {
|
|
28529
|
-
acc[item.route] = {
|
|
28530
|
-
// Navigating to a new route (passed in the second parameter)
|
|
28531
|
-
onmatch: (args) => {
|
|
28532
|
-
// Automatically close all dialogs
|
|
28533
|
-
view.popAllDialogs();
|
|
28534
|
-
view.resetScale();
|
|
28535
|
-
actions.onNavigateTo(item.name, args, view);
|
|
28536
|
-
},
|
|
28537
|
-
// Render a view on a model
|
|
28538
|
-
render: () => {
|
|
28539
|
-
return view.appView(item.name);
|
|
28540
|
-
},
|
|
28541
|
-
};
|
|
28542
|
-
return acc;
|
|
28543
|
-
}, {});
|
|
28544
|
-
}
|
|
28545
|
-
|
|
28546
|
-
/*
|
|
28547
|
-
|
|
28548
|
-
i8n.ts
|
|
28549
|
-
|
|
28550
|
-
Single page UI for Netskrafl/Explo using the Mithril library
|
|
28551
|
-
|
|
28552
|
-
Copyright (C) 2025 Miðeind ehf.
|
|
28553
|
-
Author: Vilhjálmur Þorsteinsson
|
|
28554
|
-
|
|
28555
|
-
The Creative Commons Attribution-NonCommercial 4.0
|
|
28556
|
-
International Public License (CC-BY-NC 4.0) applies to this software.
|
|
28557
|
-
For further information, see https://github.com/mideind/Netskrafl
|
|
28558
|
-
|
|
28559
|
-
|
|
28560
|
-
This module contains internationalization (i18n) utility functions,
|
|
28561
|
-
allowing for translation of displayed text between languages.
|
|
28562
|
-
|
|
28563
|
-
Text messages for individual locales are loaded from the
|
|
28564
|
-
/static/assets/messages.json file, which is fetched from the server.
|
|
28565
|
-
|
|
28566
|
-
*/
|
|
28567
|
-
// Current exact user locale and fallback locale ("en" for "en_US"/"en_GB"/...)
|
|
28568
|
-
// This is overwritten in setLocale()
|
|
28569
|
-
let currentLocale = 'is_IS';
|
|
28570
|
-
let currentFallback = 'is';
|
|
28571
|
-
// Regex that matches embedded interpolations such as "Welcome, {username}!"
|
|
28572
|
-
// Interpolation identifiers should only contain ASCII characters, digits and '_'
|
|
28573
|
-
const rex = /{\s*(\w+)\s*}/g;
|
|
28574
|
-
let messages = {};
|
|
28575
|
-
let messagesLoaded = false;
|
|
28576
|
-
function hasAnyTranslation(msgs, locale) {
|
|
28577
|
-
// Return true if any translation is available for the given locale
|
|
28578
|
-
for (const key in msgs) {
|
|
28579
|
-
if (msgs[key][locale] !== undefined)
|
|
28580
|
-
return true;
|
|
28581
|
-
}
|
|
28582
|
-
return false;
|
|
28583
|
-
}
|
|
28584
|
-
function setLocale(locale, msgs) {
|
|
28585
|
-
// Set the current i18n locale and fallback
|
|
28586
|
-
currentLocale = locale;
|
|
28587
|
-
currentFallback = locale.split('_')[0];
|
|
28588
|
-
// For unsupported locales, i.e. locales that have no
|
|
28589
|
-
// translations available for them, fall back to English (U.S.).
|
|
28590
|
-
if (!hasAnyTranslation(msgs, currentLocale) &&
|
|
28591
|
-
!hasAnyTranslation(msgs, currentFallback)) {
|
|
28592
|
-
currentLocale = 'en_US';
|
|
28593
|
-
currentFallback = 'en';
|
|
28594
|
-
}
|
|
28595
|
-
// Flatten the Messages structure, enabling long strings
|
|
28596
|
-
// to be represented as string arrays in the messages.json file
|
|
28597
|
-
messages = {};
|
|
28598
|
-
for (const key in msgs) {
|
|
28599
|
-
for (const lc in msgs[key]) {
|
|
28600
|
-
let s = msgs[key][lc];
|
|
28601
|
-
if (Array.isArray(s))
|
|
28602
|
-
s = s.join('');
|
|
28603
|
-
if (messages[key] === undefined)
|
|
28604
|
-
messages[key] = {};
|
|
28605
|
-
// If the string s contains HTML markup of the form <tag>...</tag>,
|
|
28606
|
-
// convert it into a list of Mithril Vnode children corresponding to
|
|
28607
|
-
// the text and the tags
|
|
28608
|
-
if (s.match(/<[a-z]+>/)) {
|
|
28609
|
-
// Looks like the string contains HTML markup
|
|
28610
|
-
const vnodes = [];
|
|
28611
|
-
let i = 0;
|
|
28612
|
-
let tagMatch = null;
|
|
28613
|
-
while (i < s.length &&
|
|
28614
|
-
// biome-ignore lint/suspicious/noAssignInExpressions: Done for efficiency
|
|
28615
|
-
(tagMatch = s.slice(i).match(/<[a-z]+>/)) &&
|
|
28616
|
-
tagMatch.index !== undefined) {
|
|
28617
|
-
// Found what looks like an HTML tag
|
|
28618
|
-
// Calculate the index of the enclosed text within s
|
|
28619
|
-
const tag = tagMatch[0];
|
|
28620
|
-
const j = i + tagMatch.index + tag.length;
|
|
28621
|
-
// Find the end tag
|
|
28622
|
-
const end = s.indexOf(`</${tag.slice(1)}`, j);
|
|
28623
|
-
if (end < 0) {
|
|
28624
|
-
// No end tag - skip past this weirdness
|
|
28625
|
-
i = j;
|
|
28626
|
-
continue;
|
|
28627
|
-
}
|
|
28628
|
-
// Add the text preceding the tag
|
|
28629
|
-
if (tagMatch.index > 0)
|
|
28630
|
-
vnodes.push(s.slice(i, i + tagMatch.index));
|
|
28631
|
-
// Create the Mithril node corresponding to the tag and the enclosed text
|
|
28632
|
-
// and add it to the list
|
|
28633
|
-
vnodes.push(m(tag.slice(1, -1), s.slice(j, end)));
|
|
28634
|
-
// Advance the index past the end of the tag
|
|
28635
|
-
i = end + tag.length + 1;
|
|
28636
|
-
}
|
|
28637
|
-
// Push the final text part, if any
|
|
28638
|
-
if (i < s.length)
|
|
28639
|
-
vnodes.push(s.slice(i));
|
|
28640
|
-
// Reassign s to the list of vnodes
|
|
28641
|
-
s = vnodes;
|
|
28642
|
-
}
|
|
28643
|
-
messages[key][lc] = s;
|
|
28644
|
-
}
|
|
28645
|
-
}
|
|
28646
|
-
messagesLoaded = true;
|
|
28647
|
-
}
|
|
28648
|
-
async function loadMessages(state, locale) {
|
|
28649
|
-
// Load the internationalization message JSON file from the server
|
|
28650
|
-
// and set the user's locale
|
|
28651
|
-
try {
|
|
28652
|
-
const messages = await requestWithoutAuth(state, {
|
|
28653
|
-
method: 'GET',
|
|
28654
|
-
url: '/static/assets/messages.json',
|
|
28655
|
-
withCredentials: false, // Cookies are not allowed for CORS request
|
|
28656
|
-
});
|
|
28657
|
-
setLocale(locale, messages);
|
|
28658
|
-
}
|
|
28659
|
-
catch {
|
|
28660
|
-
setLocale(locale, {});
|
|
28661
|
-
}
|
|
28662
|
-
}
|
|
28663
|
-
function t(key, ips = {}) {
|
|
28664
|
-
// Main text translation function, supporting interpolation
|
|
28665
|
-
// and HTML tag substitution
|
|
28666
|
-
const msgDict = messages[key];
|
|
28667
|
-
if (msgDict === undefined)
|
|
28668
|
-
// No dictionary for this key - may actually be a missing entry
|
|
28669
|
-
return messagesLoaded ? key : '';
|
|
28670
|
-
// Lookup exact locale, then fallback, then resort to returning the key
|
|
28671
|
-
const message = msgDict[currentLocale] || msgDict[currentFallback] || key;
|
|
28672
|
-
// If we have an interpolation object, do the interpolation first
|
|
28673
|
-
return Object.keys(ips).length ? interpolate(message, ips) : message;
|
|
28674
|
-
}
|
|
28675
|
-
function ts(key, ips = {}) {
|
|
28676
|
-
// String translation function, supporting interpolation
|
|
28677
|
-
// but not HTML tag substitution
|
|
28678
|
-
const msgDict = messages[key];
|
|
28679
|
-
if (msgDict === undefined)
|
|
28680
|
-
// No dictionary for this key - may actually be a missing entry
|
|
28681
|
-
return messagesLoaded ? key : '';
|
|
28682
|
-
// Lookup exact locale, then fallback, then resort to returning the key
|
|
28683
|
-
const message = msgDict[currentLocale] || msgDict[currentFallback] || key;
|
|
28684
|
-
if (typeof message !== 'string')
|
|
28685
|
-
// This is actually an error - the client should be calling t() instead
|
|
28686
|
-
return '';
|
|
28687
|
-
// If we have an interpolation object, do the interpolation first
|
|
28688
|
-
return Object.keys(ips).length ? interpolate_string(message, ips) : message;
|
|
28689
|
-
}
|
|
28690
|
-
function mt(cls, children) {
|
|
28691
|
-
// Wrapper for the Mithril m() function that auto-translates
|
|
28692
|
-
// string and array arguments
|
|
28693
|
-
if (typeof children === 'string') {
|
|
28694
|
-
return m(cls, t(children));
|
|
30605
|
+
word,
|
|
30606
|
+
score,
|
|
30607
|
+
coord,
|
|
30608
|
+
timestamp,
|
|
30609
|
+
});
|
|
30610
|
+
}
|
|
30611
|
+
m.redraw();
|
|
28695
30612
|
}
|
|
28696
|
-
|
|
28697
|
-
|
|
30613
|
+
async fetchRiddle(date, locale) {
|
|
30614
|
+
// Create the riddle via the model
|
|
30615
|
+
if (!this.model)
|
|
30616
|
+
throw new Error('Model is not initialized');
|
|
30617
|
+
await this.model.initRiddle(date, locale);
|
|
30618
|
+
// Attach Firebase listeners
|
|
30619
|
+
this.attachListenerToRiddle(date, locale);
|
|
28698
30620
|
}
|
|
28699
|
-
|
|
28700
|
-
|
|
28701
|
-
|
|
28702
|
-
|
|
28703
|
-
|
|
28704
|
-
|
|
30621
|
+
async loadRiddle(date, locale) {
|
|
30622
|
+
// Load a specific riddle date, handling cleanup of previous listeners
|
|
30623
|
+
// Prevent concurrent loads (e.g., from rapid navigation clicks)
|
|
30624
|
+
if (this.riddleLoading)
|
|
30625
|
+
return;
|
|
30626
|
+
this.riddleLoading = true;
|
|
30627
|
+
try {
|
|
30628
|
+
const currentRiddle = this.model.riddle;
|
|
30629
|
+
const today = new Date().toISOString().split('T')[0];
|
|
30630
|
+
const MIN_DATE = GATA_DAGSINS_MIN_DATE; // Earliest allowed date
|
|
30631
|
+
let effectiveDate = date;
|
|
30632
|
+
if (effectiveDate < MIN_DATE || effectiveDate > today) {
|
|
30633
|
+
effectiveDate = today;
|
|
30634
|
+
// Update URL to reflect the corrected date
|
|
30635
|
+
const url = new URL(window.location.href);
|
|
30636
|
+
url.searchParams.set('date', effectiveDate);
|
|
30637
|
+
window.history.pushState({}, '', url.toString());
|
|
30638
|
+
}
|
|
30639
|
+
// If we have an existing riddle, detach its listeners first
|
|
30640
|
+
if (currentRiddle) {
|
|
30641
|
+
this.detachListenerFromRiddle(currentRiddle.date, currentRiddle.locale);
|
|
30642
|
+
}
|
|
30643
|
+
// Fetch and initialize the new riddle
|
|
30644
|
+
await this.fetchRiddle(effectiveDate, locale);
|
|
30645
|
+
m.redraw();
|
|
30646
|
+
}
|
|
30647
|
+
finally {
|
|
30648
|
+
this.riddleLoading = false;
|
|
30649
|
+
}
|
|
28705
30650
|
}
|
|
28706
|
-
|
|
28707
|
-
|
|
30651
|
+
cleanupRiddle(date, locale) {
|
|
30652
|
+
// Detach Firebase listeners
|
|
30653
|
+
this.detachListenerFromRiddle(date, locale);
|
|
28708
30654
|
}
|
|
28709
|
-
|
|
28710
|
-
|
|
28711
|
-
|
|
28712
|
-
|
|
28713
|
-
|
|
30655
|
+
} // class Actions
|
|
30656
|
+
function createRouteResolver(actions, view) {
|
|
30657
|
+
// Return a map of routes to onmatch and render functions
|
|
30658
|
+
const model = actions.model;
|
|
30659
|
+
// let state = model.state;
|
|
30660
|
+
return model.paths.reduce((acc, item) => {
|
|
30661
|
+
acc[item.route] = {
|
|
30662
|
+
// Navigating to a new route (passed in the second parameter)
|
|
30663
|
+
onmatch: (args) => {
|
|
30664
|
+
// Automatically close all dialogs
|
|
30665
|
+
view.popAllDialogs();
|
|
30666
|
+
view.resetScale();
|
|
30667
|
+
actions.onNavigateTo(item.name, args, view);
|
|
30668
|
+
},
|
|
30669
|
+
// Render a view on a model
|
|
30670
|
+
render: () => {
|
|
30671
|
+
return view.appView(item.name);
|
|
30672
|
+
},
|
|
30673
|
+
};
|
|
30674
|
+
return acc;
|
|
30675
|
+
}, {});
|
|
28714
30676
|
}
|
|
28715
30677
|
|
|
28716
30678
|
/*
|
|
@@ -29527,11 +31489,11 @@ const Buttons = {
|
|
|
29527
31489
|
game.player !== null) {
|
|
29528
31490
|
// Indicate that it is the opponent's turn; offer to force a resignation
|
|
29529
31491
|
// if the opponent hasn't moved for 14 days
|
|
31492
|
+
const opponentName = game.nickname[1 - game.player];
|
|
29530
31493
|
r.push(m('.opp-turn', { style: { visibility: 'visible' } }, [
|
|
29531
31494
|
m('span.move-indicator'),
|
|
29532
31495
|
nbsp(),
|
|
29533
|
-
m('strong',
|
|
29534
|
-
ts(' á leik'),
|
|
31496
|
+
m('strong', ts('opp_move', { opponent: opponentName })),
|
|
29535
31497
|
nbsp(),
|
|
29536
31498
|
// The following inline button is only
|
|
29537
31499
|
// displayed in the fullscreen UI
|
|
@@ -30127,76 +32089,74 @@ const BoardArea = {
|
|
|
30127
32089
|
return m('.board-area', r);
|
|
30128
32090
|
},
|
|
30129
32091
|
};
|
|
30130
|
-
const Board =
|
|
32092
|
+
const Board = {
|
|
30131
32093
|
// The game board, a 15x15 table plus row (A-O) and column (1-15) identifiers
|
|
30132
|
-
|
|
30133
|
-
|
|
30134
|
-
//
|
|
30135
|
-
const
|
|
30136
|
-
|
|
30137
|
-
|
|
30138
|
-
|
|
30139
|
-
|
|
30140
|
-
|
|
30141
|
-
function row(rowid) {
|
|
30142
|
-
// Each row of the board
|
|
30143
|
-
const r = [];
|
|
30144
|
-
r.push(m('td.rowid', { key: `R${rowid}` }, rowid));
|
|
30145
|
-
for (let col = 1; col <= 15; col++) {
|
|
30146
|
-
const coord = rowid + col.toString();
|
|
30147
|
-
if (game && coord in game.tiles)
|
|
30148
|
-
// There is a tile in this square: render it
|
|
30149
|
-
r.push(m(TileSquare, {
|
|
30150
|
-
view,
|
|
30151
|
-
game,
|
|
30152
|
-
key: coord,
|
|
30153
|
-
coord: coord,
|
|
30154
|
-
opponent: false,
|
|
30155
|
-
}));
|
|
30156
|
-
else if (review)
|
|
30157
|
-
// Empty, inert square
|
|
30158
|
-
r.push(m(ReviewTileSquare, {
|
|
30159
|
-
view,
|
|
30160
|
-
game,
|
|
30161
|
-
key: coord,
|
|
30162
|
-
coord: coord,
|
|
30163
|
-
opponent: false,
|
|
30164
|
-
}));
|
|
30165
|
-
// Empty square which is a drop target
|
|
30166
|
-
else
|
|
30167
|
-
r.push(m(DropTargetSquare, {
|
|
30168
|
-
view,
|
|
30169
|
-
game,
|
|
30170
|
-
key: coord,
|
|
30171
|
-
coord: coord,
|
|
30172
|
-
}));
|
|
30173
|
-
}
|
|
30174
|
-
return m('tr', r);
|
|
30175
|
-
}
|
|
30176
|
-
function allrows() {
|
|
30177
|
-
// Return a list of all rows on the board
|
|
30178
|
-
const r = [];
|
|
30179
|
-
r.push(colid());
|
|
30180
|
-
const rows = 'ABCDEFGHIJKLMNO';
|
|
30181
|
-
for (const rw of rows)
|
|
30182
|
-
r.push(row(rw));
|
|
30183
|
-
return r;
|
|
30184
|
-
}
|
|
30185
|
-
return {
|
|
30186
|
-
view: () => {
|
|
30187
|
-
// const scale = view.boardScale || 1.0;
|
|
30188
|
-
const attrs = {};
|
|
30189
|
-
// Add handlers for pinch zoom functionality
|
|
30190
|
-
// Note: resist the temptation to pass zoomIn/zoomOut directly,
|
|
30191
|
-
// as that would not bind the 'this' pointer correctly
|
|
30192
|
-
addPinchZoom(attrs, () => view.zoomIn(), () => view.zoomOut());
|
|
30193
|
-
/*
|
|
32094
|
+
view: (vnode) => {
|
|
32095
|
+
const { view, game, review } = vnode.attrs;
|
|
32096
|
+
// const scale = view.boardScale || 1.0;
|
|
32097
|
+
const attrs = {};
|
|
32098
|
+
// Add handlers for pinch zoom functionality
|
|
32099
|
+
// Note: resist the temptation to pass zoomIn/zoomOut directly,
|
|
32100
|
+
// as that would not bind the 'this' pointer correctly
|
|
32101
|
+
addPinchZoom(attrs, () => view.zoomIn(), () => view.zoomOut());
|
|
32102
|
+
/*
|
|
30194
32103
|
if (scale !== 1.0)
|
|
30195
32104
|
attrs.style = `transform: scale(${scale})`;
|
|
30196
32105
|
*/
|
|
30197
|
-
|
|
30198
|
-
|
|
30199
|
-
|
|
32106
|
+
function colid() {
|
|
32107
|
+
// The column identifier row
|
|
32108
|
+
const r = [];
|
|
32109
|
+
r.push(m('td'));
|
|
32110
|
+
for (let col = 1; col <= 15; col++)
|
|
32111
|
+
r.push(m('td', col.toString()));
|
|
32112
|
+
return m('tr.colid', r);
|
|
32113
|
+
}
|
|
32114
|
+
function row(rowid) {
|
|
32115
|
+
// Each row of the board
|
|
32116
|
+
const r = [];
|
|
32117
|
+
r.push(m('td.rowid', { key: `R${rowid}` }, rowid));
|
|
32118
|
+
for (let col = 1; col <= 15; col++) {
|
|
32119
|
+
const coord = rowid + col.toString();
|
|
32120
|
+
if (game && coord in game.tiles)
|
|
32121
|
+
// There is a tile in this square: render it
|
|
32122
|
+
r.push(m(TileSquare, {
|
|
32123
|
+
view,
|
|
32124
|
+
game,
|
|
32125
|
+
key: coord,
|
|
32126
|
+
coord: coord,
|
|
32127
|
+
opponent: false,
|
|
32128
|
+
}));
|
|
32129
|
+
else if (review)
|
|
32130
|
+
// Empty, inert square
|
|
32131
|
+
r.push(m(ReviewTileSquare, {
|
|
32132
|
+
view,
|
|
32133
|
+
game,
|
|
32134
|
+
key: coord,
|
|
32135
|
+
coord: coord,
|
|
32136
|
+
opponent: false,
|
|
32137
|
+
}));
|
|
32138
|
+
// Empty square which is a drop target
|
|
32139
|
+
else
|
|
32140
|
+
r.push(m(DropTargetSquare, {
|
|
32141
|
+
view,
|
|
32142
|
+
game,
|
|
32143
|
+
key: coord,
|
|
32144
|
+
coord: coord,
|
|
32145
|
+
}));
|
|
32146
|
+
}
|
|
32147
|
+
return m('tr', r);
|
|
32148
|
+
}
|
|
32149
|
+
function allrows() {
|
|
32150
|
+
// Return a list of all rows on the board
|
|
32151
|
+
const r = [];
|
|
32152
|
+
r.push(colid());
|
|
32153
|
+
const rows = 'ABCDEFGHIJKLMNO';
|
|
32154
|
+
for (const rw of rows)
|
|
32155
|
+
r.push(row(rw));
|
|
32156
|
+
return r;
|
|
32157
|
+
}
|
|
32158
|
+
return m('.board', { id: 'board-parent' }, m('table.board', attrs, m('tbody', allrows())));
|
|
32159
|
+
},
|
|
30200
32160
|
};
|
|
30201
32161
|
|
|
30202
32162
|
/*
|
|
@@ -30410,6 +32370,90 @@ const GataDagsinsHelp = {
|
|
|
30410
32370
|
},
|
|
30411
32371
|
};
|
|
30412
32372
|
|
|
32373
|
+
/*
|
|
32374
|
+
|
|
32375
|
+
DateNavigator.ts
|
|
32376
|
+
|
|
32377
|
+
Component for navigating between Gáta Dagsins dates
|
|
32378
|
+
|
|
32379
|
+
Copyright (C) 2025 Miðeind ehf.
|
|
32380
|
+
Author: Vilhjálmur Þorsteinsson
|
|
32381
|
+
|
|
32382
|
+
The Creative Commons Attribution-NonCommercial 4.0
|
|
32383
|
+
International Public License (CC-BY-NC 4.0) applies to this software.
|
|
32384
|
+
For further information, see https://github.com/mideind/Netskrafl
|
|
32385
|
+
|
|
32386
|
+
*/
|
|
32387
|
+
const DateNavigator = {
|
|
32388
|
+
view: (vnode) => {
|
|
32389
|
+
const { view, date, locale } = vnode.attrs;
|
|
32390
|
+
const { actions } = view;
|
|
32391
|
+
// Helper to add days to a YYYY-MM-DD string
|
|
32392
|
+
const addDays = (dateStr, days) => {
|
|
32393
|
+
// Create date object in UTC to ensure calculations are timezone-agnostic
|
|
32394
|
+
const d = new Date(`${dateStr}T00:00:00Z`);
|
|
32395
|
+
d.setUTCDate(d.getUTCDate() + days);
|
|
32396
|
+
return d.toISOString().split('T')[0];
|
|
32397
|
+
};
|
|
32398
|
+
const today = new Date().toISOString().split('T')[0];
|
|
32399
|
+
const prevDate = addDays(date, -1);
|
|
32400
|
+
const nextDate = addDays(date, 1);
|
|
32401
|
+
const isLoading = actions.isRiddleLoading;
|
|
32402
|
+
// Disable navigation while loading or when at date boundaries
|
|
32403
|
+
const prevEnabled = !isLoading && prevDate >= GATA_DAGSINS_MIN_DATE;
|
|
32404
|
+
const nextEnabled = !isLoading && nextDate <= today;
|
|
32405
|
+
const navigateTo = (newDate) => {
|
|
32406
|
+
// Update URL without reloading the page
|
|
32407
|
+
const url = new URL(window.location.href);
|
|
32408
|
+
url.searchParams.set('date', newDate);
|
|
32409
|
+
window.history.pushState({}, '', url.toString());
|
|
32410
|
+
// Load the new riddle via the actions controller
|
|
32411
|
+
actions.loadRiddle(newDate, locale);
|
|
32412
|
+
};
|
|
32413
|
+
// Keyboard handler for Enter/Space key activation
|
|
32414
|
+
const handleKeydown = (enabled, action) => {
|
|
32415
|
+
if (!enabled)
|
|
32416
|
+
return undefined;
|
|
32417
|
+
return (e) => {
|
|
32418
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
32419
|
+
e.preventDefault();
|
|
32420
|
+
action();
|
|
32421
|
+
}
|
|
32422
|
+
};
|
|
32423
|
+
};
|
|
32424
|
+
const tsPrevDay = ts('Fyrri dagur');
|
|
32425
|
+
const tsNextDay = ts('Næsti dagur');
|
|
32426
|
+
return m('.date-navigator', [
|
|
32427
|
+
// Previous day button
|
|
32428
|
+
m(`.nav-arrow.prev${prevEnabled ? '' : '.disabled'}`, {
|
|
32429
|
+
role: 'button',
|
|
32430
|
+
tabindex: prevEnabled ? 0 : -1,
|
|
32431
|
+
'aria-disabled': !prevEnabled,
|
|
32432
|
+
'aria-label': tsPrevDay,
|
|
32433
|
+
onclick: prevEnabled
|
|
32434
|
+
? () => navigateTo(prevDate)
|
|
32435
|
+
: undefined,
|
|
32436
|
+
onkeydown: handleKeydown(prevEnabled, () => navigateTo(prevDate)),
|
|
32437
|
+
title: prevEnabled ? tsPrevDay : '',
|
|
32438
|
+
}, glyph('chevron-left')),
|
|
32439
|
+
// Date display
|
|
32440
|
+
m('.nav-date', formatDate(date)),
|
|
32441
|
+
// Next day button
|
|
32442
|
+
m(`.nav-arrow.next${nextEnabled ? '' : '.disabled'}`, {
|
|
32443
|
+
role: 'button',
|
|
32444
|
+
tabindex: nextEnabled ? 0 : -1,
|
|
32445
|
+
'aria-disabled': !nextEnabled,
|
|
32446
|
+
'aria-label': tsNextDay,
|
|
32447
|
+
onclick: nextEnabled
|
|
32448
|
+
? () => navigateTo(nextDate)
|
|
32449
|
+
: undefined,
|
|
32450
|
+
onkeydown: handleKeydown(nextEnabled, () => navigateTo(nextDate)),
|
|
32451
|
+
title: nextEnabled ? tsNextDay : '',
|
|
32452
|
+
}, glyph('chevron-right')),
|
|
32453
|
+
]);
|
|
32454
|
+
},
|
|
32455
|
+
};
|
|
32456
|
+
|
|
30413
32457
|
/*
|
|
30414
32458
|
|
|
30415
32459
|
SunCorona.ts
|
|
@@ -30483,6 +32527,13 @@ const SunCorona = {
|
|
|
30483
32527
|
*/
|
|
30484
32528
|
// Mobile-only horizontal status display
|
|
30485
32529
|
const MobileStatus = () => {
|
|
32530
|
+
// Keyboard handler for button activation
|
|
32531
|
+
const handleKeydown = (action) => (e) => {
|
|
32532
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
32533
|
+
e.preventDefault();
|
|
32534
|
+
action();
|
|
32535
|
+
}
|
|
32536
|
+
};
|
|
30486
32537
|
return {
|
|
30487
32538
|
view: (vnode) => {
|
|
30488
32539
|
const { view, bestMove, onMoveClick, onStatsClick } = vnode.attrs;
|
|
@@ -30492,6 +32543,12 @@ const MobileStatus = () => {
|
|
|
30492
32543
|
const { bestPossibleScore, globalBestScore, personalBestScore } = riddle;
|
|
30493
32544
|
// Determine if player achieved best possible score
|
|
30494
32545
|
const celebrate = bestMove && bestMove.word !== '';
|
|
32546
|
+
const today = new Date().toISOString().split('T')[0];
|
|
32547
|
+
const lookingAtOldRiddle = riddle.date < today;
|
|
32548
|
+
// If we don't have an explicit solution, use the global best score as fallback
|
|
32549
|
+
const solution = lookingAtOldRiddle
|
|
32550
|
+
? riddle.solution || globalBestScore
|
|
32551
|
+
: null;
|
|
30495
32552
|
// Determine current leader score (may be this player or another)
|
|
30496
32553
|
let leaderScore = 0;
|
|
30497
32554
|
let isPlayerLeading = false;
|
|
@@ -30504,13 +32561,32 @@ const MobileStatus = () => {
|
|
|
30504
32561
|
leaderScore = personalBestScore;
|
|
30505
32562
|
isPlayerLeading = personalBestScore > 0;
|
|
30506
32563
|
}
|
|
32564
|
+
// Handler for clicking on best possible score
|
|
32565
|
+
const isScoreClickable = !!(solution || celebrate);
|
|
32566
|
+
const handleScoreClick = () => {
|
|
32567
|
+
if (solution) {
|
|
32568
|
+
// Zoom out when showing solution for old riddles
|
|
32569
|
+
view.zoomOut();
|
|
32570
|
+
// Recreate the solution word on the board
|
|
32571
|
+
onMoveClick(solution.word, solution.coord);
|
|
32572
|
+
}
|
|
32573
|
+
else if (celebrate) {
|
|
32574
|
+
// Recreate the best move word on the board
|
|
32575
|
+
onMoveClick(bestMove.word, bestMove.coord);
|
|
32576
|
+
}
|
|
32577
|
+
};
|
|
32578
|
+
const tsStatsAndLeaderboard = ts('Tölfræði og stigatafla');
|
|
30507
32579
|
return m('.mobile-status-container', [
|
|
30508
32580
|
// Current word score (leftmost) - uses RiddleScore component in mobile mode
|
|
30509
32581
|
m('.mobile-status-item.left', m(RiddleScore, { riddle, mode: 'mobile' })),
|
|
30510
32582
|
// Interactive card containing player best and leader scores
|
|
30511
32583
|
m('.mobile-status-card', {
|
|
32584
|
+
role: 'button',
|
|
32585
|
+
tabindex: 0,
|
|
32586
|
+
'aria-label': tsStatsAndLeaderboard,
|
|
30512
32587
|
onclick: onStatsClick,
|
|
30513
|
-
|
|
32588
|
+
onkeydown: handleKeydown(onStatsClick),
|
|
32589
|
+
title: tsStatsAndLeaderboard,
|
|
30514
32590
|
}, [
|
|
30515
32591
|
// Player's best score
|
|
30516
32592
|
m('.mobile-status-card-item.player-best', [
|
|
@@ -30531,8 +32607,15 @@ const MobileStatus = () => {
|
|
|
30531
32607
|
// Best possible score
|
|
30532
32608
|
m('.mobile-status-item.right.best-possible' +
|
|
30533
32609
|
(celebrate ? '.celebrate' : ''), {
|
|
30534
|
-
|
|
30535
|
-
|
|
32610
|
+
role: isScoreClickable ? 'button' : undefined,
|
|
32611
|
+
tabindex: isScoreClickable ? 0 : undefined,
|
|
32612
|
+
'aria-label': isScoreClickable
|
|
32613
|
+
? ts('Sýna besta leik')
|
|
32614
|
+
: undefined,
|
|
32615
|
+
onclick: handleScoreClick,
|
|
32616
|
+
onkeydown: isScoreClickable
|
|
32617
|
+
? handleKeydown(handleScoreClick)
|
|
32618
|
+
: undefined,
|
|
30536
32619
|
}, [
|
|
30537
32620
|
// Wrapper for score and corona to position them together
|
|
30538
32621
|
m('.mobile-best-score-wrapper', [
|
|
@@ -30573,30 +32656,9 @@ function getMedalIcon(rank) {
|
|
|
30573
32656
|
return null;
|
|
30574
32657
|
}
|
|
30575
32658
|
}
|
|
30576
|
-
function formatDate(dateStr) {
|
|
30577
|
-
// Format YYYY-MM-DD to Icelandic date (e.g., "2. okt.")
|
|
30578
|
-
const date = new Date(`${dateStr}T00:00:00`);
|
|
30579
|
-
const day = date.getDate();
|
|
30580
|
-
const months = [
|
|
30581
|
-
'janúar',
|
|
30582
|
-
'febrúar',
|
|
30583
|
-
'mars',
|
|
30584
|
-
'apríl',
|
|
30585
|
-
'maí',
|
|
30586
|
-
'júní',
|
|
30587
|
-
'júlí',
|
|
30588
|
-
'ágúst',
|
|
30589
|
-
'september',
|
|
30590
|
-
'október',
|
|
30591
|
-
'nóvember',
|
|
30592
|
-
'desember',
|
|
30593
|
-
];
|
|
30594
|
-
const month = months[date.getMonth()];
|
|
30595
|
-
return `${day}. ${month}`;
|
|
30596
|
-
}
|
|
30597
32659
|
const LeaderboardView = {
|
|
30598
32660
|
view: (vnode) => {
|
|
30599
|
-
const { leaderboard, currentUserId,
|
|
32661
|
+
const { leaderboard, currentUserId, loading = false } = vnode.attrs;
|
|
30600
32662
|
if (loading) {
|
|
30601
32663
|
return m('.leaderboard-view.loading', m('.loading-message', ts('Hleð stigatöflu...')));
|
|
30602
32664
|
}
|
|
@@ -30604,9 +32666,6 @@ const LeaderboardView = {
|
|
|
30604
32666
|
return m('.leaderboard-view.empty', m('.empty-message', ts('Engin stig skráð enn')));
|
|
30605
32667
|
}
|
|
30606
32668
|
return m('.leaderboard-view', [
|
|
30607
|
-
m('.leaderboard-header', [
|
|
30608
|
-
m('.leaderboard-title', formatDate(date)),
|
|
30609
|
-
]),
|
|
30610
32669
|
m('.leaderboard-list', {
|
|
30611
32670
|
// Allow touch scrolling but prevent events from bubbling to backdrop
|
|
30612
32671
|
ontouchmove: (e) => {
|
|
@@ -30714,22 +32773,37 @@ const StatsView = {
|
|
|
30714
32773
|
const TabBar = {
|
|
30715
32774
|
view: (vnode) => {
|
|
30716
32775
|
const { tabs, activeTab, onTabChange } = vnode.attrs;
|
|
30717
|
-
|
|
30718
|
-
|
|
30719
|
-
|
|
30720
|
-
|
|
30721
|
-
|
|
30722
|
-
|
|
30723
|
-
|
|
30724
|
-
|
|
30725
|
-
|
|
32776
|
+
// Keyboard handler for tab activation
|
|
32777
|
+
const handleKeydown = (tabId) => (e) => {
|
|
32778
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
32779
|
+
e.preventDefault();
|
|
32780
|
+
onTabChange(tabId);
|
|
32781
|
+
}
|
|
32782
|
+
};
|
|
32783
|
+
return m('.tab-bar[role=tablist]', tabs.map((tab) => {
|
|
32784
|
+
const isActive = activeTab === tab.id;
|
|
32785
|
+
return m(`.tab-item${isActive ? '.active' : ''}`, {
|
|
32786
|
+
key: tab.id,
|
|
32787
|
+
role: 'tab',
|
|
32788
|
+
tabindex: isActive ? 0 : -1,
|
|
32789
|
+
'aria-selected': isActive,
|
|
32790
|
+
'aria-label': tab.label,
|
|
32791
|
+
onclick: () => onTabChange(tab.id),
|
|
32792
|
+
onkeydown: handleKeydown(tab.id),
|
|
32793
|
+
}, [
|
|
32794
|
+
m('span.tab-icon-wrapper', [
|
|
32795
|
+
tab.iconGlyph
|
|
32796
|
+
? m('span.tab-icon', glyph(tab.iconGlyph))
|
|
32797
|
+
: tab.icon
|
|
32798
|
+
? m('span.tab-icon', tab.icon)
|
|
32799
|
+
: null,
|
|
32800
|
+
tab.badgeGlyph
|
|
32801
|
+
? m('span.tab-badge', glyph(tab.badgeGlyph))
|
|
30726
32802
|
: null,
|
|
30727
|
-
|
|
30728
|
-
|
|
30729
|
-
|
|
30730
|
-
|
|
30731
|
-
m('span.tab-label', tab.label),
|
|
30732
|
-
])));
|
|
32803
|
+
]),
|
|
32804
|
+
m('span.tab-label', tab.label),
|
|
32805
|
+
]);
|
|
32806
|
+
}));
|
|
30733
32807
|
},
|
|
30734
32808
|
};
|
|
30735
32809
|
|
|
@@ -30803,156 +32877,200 @@ function calculateZoneHeights(allocation) {
|
|
|
30803
32877
|
};
|
|
30804
32878
|
}
|
|
30805
32879
|
// Best possible score component (green circle at top)
|
|
30806
|
-
const BestPossibleScore =
|
|
30807
|
-
|
|
30808
|
-
|
|
30809
|
-
|
|
30810
|
-
|
|
30811
|
-
|
|
30812
|
-
|
|
30813
|
-
|
|
30814
|
-
|
|
32880
|
+
const BestPossibleScore = {
|
|
32881
|
+
view: (vnode) => {
|
|
32882
|
+
const { score, bestMove, onMoveClick, solution } = vnode.attrs;
|
|
32883
|
+
// Determine the label based on achievement status
|
|
32884
|
+
let topLabel;
|
|
32885
|
+
const celebrate = bestMove && bestMove.word !== '';
|
|
32886
|
+
if (celebrate) {
|
|
32887
|
+
// Current player achieved it - show their word
|
|
32888
|
+
topLabel = removeBlankMarkers(bestMove.word);
|
|
32889
|
+
}
|
|
32890
|
+
else {
|
|
32891
|
+
// Not achieved yet - show default label
|
|
32892
|
+
topLabel = ts('Besta mögulega lögn');
|
|
32893
|
+
}
|
|
32894
|
+
const title = solution && !celebrate ? ts('Smelltu til að sjá lausn') : '';
|
|
32895
|
+
const isClickable = !!(solution || celebrate);
|
|
32896
|
+
const handleClick = () => {
|
|
32897
|
+
if (solution) {
|
|
32898
|
+
// Recreate the solution word on the board
|
|
32899
|
+
onMoveClick(solution.word, solution.coord);
|
|
30815
32900
|
}
|
|
30816
|
-
else {
|
|
30817
|
-
//
|
|
30818
|
-
|
|
32901
|
+
else if (celebrate) {
|
|
32902
|
+
// Recreate the best move word on the board
|
|
32903
|
+
onMoveClick(bestMove.word, bestMove.coord);
|
|
30819
32904
|
}
|
|
30820
|
-
|
|
30821
|
-
|
|
30822
|
-
|
|
30823
|
-
|
|
30824
|
-
|
|
30825
|
-
|
|
30826
|
-
|
|
30827
|
-
|
|
30828
|
-
|
|
30829
|
-
|
|
30830
|
-
|
|
30831
|
-
|
|
32905
|
+
};
|
|
32906
|
+
const handleKeydown = isClickable
|
|
32907
|
+
? (e) => {
|
|
32908
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
32909
|
+
e.preventDefault();
|
|
32910
|
+
handleClick();
|
|
32911
|
+
}
|
|
32912
|
+
}
|
|
32913
|
+
: undefined;
|
|
32914
|
+
return m(`.thermometer-best-score${celebrate ? '.celebrate' : ''}`, m('.thermometer-best-score-container', {
|
|
32915
|
+
role: isClickable ? 'button' : undefined,
|
|
32916
|
+
tabindex: isClickable ? 0 : undefined,
|
|
32917
|
+
'aria-label': isClickable
|
|
32918
|
+
? ts('Sýna besta leik')
|
|
32919
|
+
: undefined,
|
|
32920
|
+
onclick: handleClick,
|
|
32921
|
+
onkeydown: handleKeydown,
|
|
32922
|
+
title,
|
|
32923
|
+
}, [
|
|
32924
|
+
// Sun corona behind the circle when celebrating
|
|
32925
|
+
celebrate ? m(SunCorona, { animate: true }) : null,
|
|
32926
|
+
m('.thermometer-best-circle', score.toString()),
|
|
32927
|
+
m('.thermometer-best-label', topLabel),
|
|
32928
|
+
]));
|
|
32929
|
+
},
|
|
30832
32930
|
};
|
|
30833
32931
|
// Current global best score component (circled score)
|
|
30834
|
-
const GlobalBestScore =
|
|
30835
|
-
|
|
30836
|
-
|
|
30837
|
-
|
|
30838
|
-
|
|
30839
|
-
},
|
|
30840
|
-
};
|
|
32932
|
+
const GlobalBestScore = {
|
|
32933
|
+
view: (vnode) => {
|
|
32934
|
+
const { score, thisPlayer } = vnode.attrs;
|
|
32935
|
+
return m(`.thermometer-current-score${thisPlayer ? '.this-player' : ''}`, [m('.thermometer-current-circle', score.toString())]);
|
|
32936
|
+
},
|
|
30841
32937
|
};
|
|
30842
32938
|
// Player moves overlay wrapper component with zone-aware positioning
|
|
30843
|
-
const PlayerMovesOverlay =
|
|
30844
|
-
|
|
30845
|
-
|
|
30846
|
-
|
|
30847
|
-
|
|
30848
|
-
|
|
30849
|
-
|
|
30850
|
-
|
|
30851
|
-
|
|
30852
|
-
|
|
30853
|
-
|
|
30854
|
-
|
|
30855
|
-
|
|
30856
|
-
|
|
30857
|
-
|
|
30858
|
-
if (move.
|
|
30859
|
-
|
|
30860
|
-
|
|
30861
|
-
|
|
30862
|
-
|
|
30863
|
-
|
|
30864
|
-
|
|
30865
|
-
|
|
30866
|
-
];
|
|
30867
|
-
}
|
|
30868
|
-
else {
|
|
30869
|
-
// This player is the holder of the top score
|
|
30870
|
-
return [
|
|
30871
|
-
m(GlobalBestScore, {
|
|
30872
|
-
thisPlayer: true,
|
|
30873
|
-
score: move.score,
|
|
30874
|
-
}),
|
|
30875
|
-
m('.thermometer-move-word', removeBlankMarkers(move.word)),
|
|
30876
|
-
m('.thermometer-move-coord', `(${move.coord})`),
|
|
30877
|
-
];
|
|
30878
|
-
}
|
|
32939
|
+
const PlayerMovesOverlay = {
|
|
32940
|
+
view: (vnode) => {
|
|
32941
|
+
// Zones: "hot", "warm", "cold"
|
|
32942
|
+
// zoneHeights: How tall each zone is, as a percentage of the thermometer height
|
|
32943
|
+
// zoneAllocation: A dictionary with the list of moves for each zone
|
|
32944
|
+
const { zoneHeights, zoneAllocation, onMoveClick } = vnode.attrs;
|
|
32945
|
+
// Calculate zone boundaries
|
|
32946
|
+
const coldBottom = 0;
|
|
32947
|
+
const coldTop = zoneHeights.cold;
|
|
32948
|
+
const warmBottom = coldTop;
|
|
32949
|
+
const warmTop = warmBottom + zoneHeights.warm;
|
|
32950
|
+
const hotBottom = warmTop;
|
|
32951
|
+
const allMoveElements = [];
|
|
32952
|
+
function scoreDetails(move) {
|
|
32953
|
+
if (move.isGlobalBestScore) {
|
|
32954
|
+
if (move.word === '') {
|
|
32955
|
+
// Another player holds the top score
|
|
32956
|
+
return [
|
|
32957
|
+
m(GlobalBestScore, {
|
|
32958
|
+
thisPlayer: false,
|
|
32959
|
+
score: move.score,
|
|
32960
|
+
}),
|
|
32961
|
+
];
|
|
30879
32962
|
}
|
|
30880
32963
|
else {
|
|
32964
|
+
// This player is the holder of the top score
|
|
30881
32965
|
return [
|
|
30882
|
-
m(
|
|
32966
|
+
m(GlobalBestScore, {
|
|
32967
|
+
thisPlayer: true,
|
|
32968
|
+
score: move.score,
|
|
32969
|
+
}),
|
|
30883
32970
|
m('.thermometer-move-word', removeBlankMarkers(move.word)),
|
|
30884
32971
|
m('.thermometer-move-coord', `(${move.coord})`),
|
|
30885
32972
|
];
|
|
30886
32973
|
}
|
|
30887
32974
|
}
|
|
30888
|
-
|
|
30889
|
-
|
|
30890
|
-
|
|
30891
|
-
|
|
30892
|
-
|
|
30893
|
-
|
|
30894
|
-
// i.e. with the highest percentage position, which is
|
|
30895
|
-
// calculated from the bottom of the thermometer.
|
|
30896
|
-
const position = zoneStart + segmentHeight * (num - index);
|
|
30897
|
-
allMoveElements.push(m(`.thermometer-move-overlay .${zoneName}`, {
|
|
30898
|
-
key: `${zoneName}-${index}`,
|
|
30899
|
-
style: `--move-position: ${position.toFixed(2)}%`,
|
|
30900
|
-
// Only call onMoveClick if the move was actually made
|
|
30901
|
-
// by the current player
|
|
30902
|
-
onclick: () => move.word &&
|
|
30903
|
-
move.coord &&
|
|
30904
|
-
onMoveClick(move.word, move.coord),
|
|
30905
|
-
}, scoreDetails(move)));
|
|
30906
|
-
});
|
|
32975
|
+
else {
|
|
32976
|
+
return [
|
|
32977
|
+
m('.thermometer-move-score', move.score.toString()),
|
|
32978
|
+
m('.thermometer-move-word', removeBlankMarkers(move.word)),
|
|
32979
|
+
m('.thermometer-move-coord', `(${move.coord})`),
|
|
32980
|
+
];
|
|
30907
32981
|
}
|
|
30908
|
-
|
|
30909
|
-
|
|
30910
|
-
|
|
30911
|
-
|
|
30912
|
-
|
|
30913
|
-
|
|
32982
|
+
}
|
|
32983
|
+
function addZoneMoves(zoneMoves, zoneName, zoneStart, zoneHeight) {
|
|
32984
|
+
const num = zoneMoves.length;
|
|
32985
|
+
const segmentHeight = zoneHeight / (num + 1);
|
|
32986
|
+
zoneMoves.forEach((move, index) => {
|
|
32987
|
+
// The zoneMoves list is in descending order, and we want
|
|
32988
|
+
// the first (highest) move to be at the top of the zone,
|
|
32989
|
+
// i.e. with the highest percentage position, which is
|
|
32990
|
+
// calculated from the bottom of the thermometer.
|
|
32991
|
+
const position = zoneStart + segmentHeight * (num - index);
|
|
32992
|
+
// Only clickable if the move was made by the current player
|
|
32993
|
+
const isClickable = !!(move.word && move.coord);
|
|
32994
|
+
const handleClick = () => {
|
|
32995
|
+
if (isClickable) {
|
|
32996
|
+
onMoveClick(move.word, move.coord);
|
|
32997
|
+
}
|
|
32998
|
+
};
|
|
32999
|
+
const handleKeydown = isClickable
|
|
33000
|
+
? (e) => {
|
|
33001
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
33002
|
+
e.preventDefault();
|
|
33003
|
+
handleClick();
|
|
33004
|
+
}
|
|
33005
|
+
}
|
|
33006
|
+
: undefined;
|
|
33007
|
+
allMoveElements.push(m(`.thermometer-move-overlay .${zoneName}`, {
|
|
33008
|
+
key: `${zoneName}-${index}`,
|
|
33009
|
+
style: `--move-position: ${position.toFixed(2)}%`,
|
|
33010
|
+
role: isClickable ? 'button' : undefined,
|
|
33011
|
+
tabindex: isClickable ? 0 : undefined,
|
|
33012
|
+
'aria-label': isClickable
|
|
33013
|
+
? `${ts('Sýna leik')}: ${removeBlankMarkers(move.word)}`
|
|
33014
|
+
: undefined,
|
|
33015
|
+
onclick: handleClick,
|
|
33016
|
+
onkeydown: handleKeydown,
|
|
33017
|
+
}, scoreDetails(move)));
|
|
33018
|
+
});
|
|
33019
|
+
}
|
|
33020
|
+
addZoneMoves(zoneAllocation.cold, 'cold', coldBottom, zoneHeights.cold);
|
|
33021
|
+
addZoneMoves(zoneAllocation.warm, 'warm', warmBottom, zoneHeights.warm);
|
|
33022
|
+
addZoneMoves(zoneAllocation.hot, 'hot', hotBottom, zoneHeights.hot);
|
|
33023
|
+
return m('.thermometer-moves-overlay-wrapper', allMoveElements);
|
|
33024
|
+
},
|
|
30914
33025
|
};
|
|
30915
33026
|
// Main thermometer component with dynamic layout algorithm
|
|
30916
|
-
const Thermometer =
|
|
30917
|
-
|
|
30918
|
-
|
|
30919
|
-
|
|
30920
|
-
|
|
30921
|
-
|
|
30922
|
-
|
|
30923
|
-
|
|
30924
|
-
|
|
30925
|
-
|
|
30926
|
-
|
|
30927
|
-
|
|
30928
|
-
|
|
30929
|
-
|
|
30930
|
-
|
|
30931
|
-
|
|
30932
|
-
|
|
30933
|
-
|
|
30934
|
-
|
|
30935
|
-
|
|
30936
|
-
|
|
30937
|
-
|
|
30938
|
-
|
|
30939
|
-
|
|
30940
|
-
|
|
30941
|
-
|
|
30942
|
-
zoneHeights
|
|
30943
|
-
zoneAllocation,
|
|
30944
|
-
onMoveClick,
|
|
33027
|
+
const Thermometer = {
|
|
33028
|
+
view: (vnode) => {
|
|
33029
|
+
const { riddle, selectedMoves, bestMove, onMoveClick } = vnode.attrs;
|
|
33030
|
+
const { warmBoundary, hotBoundary, bestPossibleScore, globalBestScore, } = riddle;
|
|
33031
|
+
const zoneAllocation = allocateMovesToZones(warmBoundary, hotBoundary, selectedMoves);
|
|
33032
|
+
const zoneHeights = calculateZoneHeights(zoneAllocation);
|
|
33033
|
+
const today = new Date().toISOString().split('T')[0];
|
|
33034
|
+
const lookingAtOldRiddle = riddle.date < today;
|
|
33035
|
+
// If we don't have an explicit solution, use the global best score as fallback
|
|
33036
|
+
const solution = lookingAtOldRiddle
|
|
33037
|
+
? riddle.solution || globalBestScore
|
|
33038
|
+
: null;
|
|
33039
|
+
return m('.thermometer-container', [
|
|
33040
|
+
// Main thermometer body with dynamic color zones and overlaid moves
|
|
33041
|
+
m('.thermometer-body', [
|
|
33042
|
+
// Dynamic color zones background
|
|
33043
|
+
m('.thermometer-zones', [
|
|
33044
|
+
m('.thermometer-zone.hot', {
|
|
33045
|
+
style: `--zone-size: ${zoneHeights.hot +
|
|
33046
|
+
zoneHeights.warm +
|
|
33047
|
+
zoneHeights.cold}%`,
|
|
33048
|
+
}),
|
|
33049
|
+
m('.thermometer-zone.warm', {
|
|
33050
|
+
style: `--zone-size: ${zoneHeights.warm + zoneHeights.cold}%`,
|
|
33051
|
+
}),
|
|
33052
|
+
m('.thermometer-zone.cold', {
|
|
33053
|
+
style: `--zone-size: ${zoneHeights.cold}%`,
|
|
30945
33054
|
}),
|
|
30946
33055
|
]),
|
|
30947
|
-
//
|
|
30948
|
-
m(
|
|
30949
|
-
|
|
30950
|
-
|
|
33056
|
+
// Player moves positioned using zone-aware algorithm
|
|
33057
|
+
m(PlayerMovesOverlay, {
|
|
33058
|
+
moves: selectedMoves,
|
|
33059
|
+
maxScore: bestPossibleScore,
|
|
33060
|
+
zoneHeights,
|
|
33061
|
+
zoneAllocation,
|
|
30951
33062
|
onMoveClick,
|
|
30952
33063
|
}),
|
|
30953
|
-
])
|
|
30954
|
-
|
|
30955
|
-
|
|
33064
|
+
]),
|
|
33065
|
+
// Best possible score at top
|
|
33066
|
+
m(BestPossibleScore, {
|
|
33067
|
+
score: bestPossibleScore,
|
|
33068
|
+
bestMove,
|
|
33069
|
+
onMoveClick,
|
|
33070
|
+
solution,
|
|
33071
|
+
}),
|
|
33072
|
+
]);
|
|
33073
|
+
},
|
|
30956
33074
|
};
|
|
30957
33075
|
|
|
30958
33076
|
/*
|
|
@@ -31029,7 +33147,6 @@ const RightSideTabs = () => {
|
|
|
31029
33147
|
? m(LeaderboardView, {
|
|
31030
33148
|
leaderboard: view.model.leaderboard || [],
|
|
31031
33149
|
currentUserId: state?.netskraflUserId || '',
|
|
31032
|
-
date: riddle.date,
|
|
31033
33150
|
loading: false,
|
|
31034
33151
|
})
|
|
31035
33152
|
: null,
|
|
@@ -31067,20 +33184,35 @@ const GataDagsinsRightSide = {
|
|
|
31067
33184
|
return m('.gatadagsins-right-side-wrapper', riddle
|
|
31068
33185
|
? [
|
|
31069
33186
|
// Mobile-only status bar (visible on mobile, hidden on desktop)
|
|
31070
|
-
|
|
31071
|
-
|
|
31072
|
-
|
|
31073
|
-
|
|
31074
|
-
|
|
31075
|
-
|
|
31076
|
-
|
|
33187
|
+
// We wrap the mobile content to include the date navigator
|
|
33188
|
+
m('.gatadagsins-mobile-wrapper', [
|
|
33189
|
+
m('.mobile-date-nav-container', m(DateNavigator, {
|
|
33190
|
+
view,
|
|
33191
|
+
date: riddle.date,
|
|
33192
|
+
locale: riddle.locale,
|
|
33193
|
+
})),
|
|
33194
|
+
m('.gatadagsins-mobile-status', m(MobileStatus, {
|
|
33195
|
+
view,
|
|
33196
|
+
selectedMoves,
|
|
33197
|
+
bestMove,
|
|
33198
|
+
onMoveClick,
|
|
33199
|
+
onStatsClick,
|
|
33200
|
+
})),
|
|
33201
|
+
]),
|
|
31077
33202
|
// Desktop-only tabbed view (hidden on mobile, visible on desktop)
|
|
31078
|
-
m('.gatadagsins-thermometer-column',
|
|
31079
|
-
|
|
31080
|
-
|
|
31081
|
-
|
|
31082
|
-
|
|
31083
|
-
|
|
33203
|
+
m('.gatadagsins-thermometer-column', [
|
|
33204
|
+
m('.desktop-date-nav-container', m(DateNavigator, {
|
|
33205
|
+
view,
|
|
33206
|
+
date: riddle.date,
|
|
33207
|
+
locale: riddle.locale,
|
|
33208
|
+
})),
|
|
33209
|
+
m(RightSideTabs, {
|
|
33210
|
+
view,
|
|
33211
|
+
selectedMoves,
|
|
33212
|
+
bestMove,
|
|
33213
|
+
onMoveClick,
|
|
33214
|
+
}),
|
|
33215
|
+
]),
|
|
31084
33216
|
]
|
|
31085
33217
|
: null);
|
|
31086
33218
|
},
|
|
@@ -31178,7 +33310,6 @@ const StatsModal = () => {
|
|
|
31178
33310
|
? m(LeaderboardView, {
|
|
31179
33311
|
leaderboard: view.model.leaderboard || [],
|
|
31180
33312
|
currentUserId: state?.netskraflUserId || '',
|
|
31181
|
-
date: riddle.date,
|
|
31182
33313
|
loading: false,
|
|
31183
33314
|
})
|
|
31184
33315
|
: null,
|
|
@@ -31894,9 +34025,9 @@ class BaseGame {
|
|
|
31894
34025
|
}
|
|
31895
34026
|
async updateScore() {
|
|
31896
34027
|
// Re-calculate the current word score
|
|
31897
|
-
const scoreResult = this.calcScore();
|
|
31898
34028
|
this.wordGood = false;
|
|
31899
34029
|
this.wordBad = false;
|
|
34030
|
+
const scoreResult = this.calcScore();
|
|
31900
34031
|
if (scoreResult === undefined || !scoreResult.word) {
|
|
31901
34032
|
this.currentScore = undefined;
|
|
31902
34033
|
this.currentWord = '';
|
|
@@ -31912,8 +34043,12 @@ class BaseGame {
|
|
|
31912
34043
|
// This is not a manual-wordcheck game:
|
|
31913
34044
|
// Check the word that has been laid down
|
|
31914
34045
|
const found = await wordChecker.checkWords(this.state, this.locale, scoreResult.words);
|
|
31915
|
-
this.
|
|
31916
|
-
|
|
34046
|
+
if (this.currentWord === scoreResult.word) {
|
|
34047
|
+
// Safety check: ensure that the current word has not changed
|
|
34048
|
+
// while the wordChecker was awaiting the server response
|
|
34049
|
+
this.wordGood = found;
|
|
34050
|
+
this.wordBad = !found;
|
|
34051
|
+
}
|
|
31917
34052
|
}
|
|
31918
34053
|
}
|
|
31919
34054
|
}
|
|
@@ -33282,6 +35417,7 @@ class Riddle extends BaseGame {
|
|
|
33282
35417
|
this.groupBestScore = null;
|
|
33283
35418
|
this.personalBestScore = 0;
|
|
33284
35419
|
this.playerMoves = [];
|
|
35420
|
+
this.solution = null;
|
|
33285
35421
|
this.date = date;
|
|
33286
35422
|
this.model = model;
|
|
33287
35423
|
}
|
|
@@ -33311,8 +35447,6 @@ class Riddle extends BaseGame {
|
|
|
33311
35447
|
return !this.showingDialog;
|
|
33312
35448
|
}
|
|
33313
35449
|
async load(date, locale) {
|
|
33314
|
-
this.date = date;
|
|
33315
|
-
this.locale = locale;
|
|
33316
35450
|
const { state } = this;
|
|
33317
35451
|
try {
|
|
33318
35452
|
if (!state)
|
|
@@ -33324,6 +35458,8 @@ class Riddle extends BaseGame {
|
|
|
33324
35458
|
body: { date, locale },
|
|
33325
35459
|
});
|
|
33326
35460
|
if (response.ok) {
|
|
35461
|
+
this.date = date;
|
|
35462
|
+
this.locale = locale;
|
|
33327
35463
|
this.board_type = response.riddle.board_type || 'standard';
|
|
33328
35464
|
this.alphabet = response.riddle.alphabet || '';
|
|
33329
35465
|
this.tile_scores = response.riddle.tile_scores || {};
|
|
@@ -33334,6 +35470,7 @@ class Riddle extends BaseGame {
|
|
|
33334
35470
|
this.globalBestScore = null;
|
|
33335
35471
|
this.groupBestScore = null;
|
|
33336
35472
|
this.personalBestScore = 0;
|
|
35473
|
+
this.solution = response.riddle.solution || null;
|
|
33337
35474
|
this.warmBoundary =
|
|
33338
35475
|
this.bestPossibleScore * WARM_COLD_BOUNDARY_RATIO;
|
|
33339
35476
|
this.hotBoundary =
|
|
@@ -33344,16 +35481,20 @@ class Riddle extends BaseGame {
|
|
|
33344
35481
|
if (state.netskraflUserId) {
|
|
33345
35482
|
const persistedMoves = loadLocalMoves(state.netskraflUserId, date);
|
|
33346
35483
|
if (persistedMoves.length > 0) {
|
|
33347
|
-
//
|
|
33348
|
-
|
|
33349
|
-
|
|
33350
|
-
|
|
33351
|
-
|
|
33352
|
-
|
|
33353
|
-
|
|
33354
|
-
|
|
33355
|
-
|
|
33356
|
-
|
|
35484
|
+
// Filter out invalid moves (score > bestPossibleScore)
|
|
35485
|
+
const validMoves = persistedMoves.filter((move) => move.score <= this.bestPossibleScore);
|
|
35486
|
+
if (validMoves.length > 0) {
|
|
35487
|
+
// Convert from IPlayerMove to RiddleWord format, preserving timestamps
|
|
35488
|
+
this.playerMoves = validMoves.map((move) => ({
|
|
35489
|
+
word: move.word,
|
|
35490
|
+
score: move.score,
|
|
35491
|
+
coord: move.coord,
|
|
35492
|
+
timestamp: move.timestamp || new Date().toISOString(), // Use stored timestamp or fallback
|
|
35493
|
+
}));
|
|
35494
|
+
// Update personal best score from valid moves only
|
|
35495
|
+
const bestMove = validMoves.reduce((best, current) => current.score > best.score ? current : best);
|
|
35496
|
+
this.personalBestScore = bestMove.score;
|
|
35497
|
+
}
|
|
33357
35498
|
}
|
|
33358
35499
|
}
|
|
33359
35500
|
}
|
|
@@ -33396,6 +35537,10 @@ class Riddle extends BaseGame {
|
|
|
33396
35537
|
!this.currentCoord) {
|
|
33397
35538
|
return;
|
|
33398
35539
|
}
|
|
35540
|
+
// Sanity check: move score cannot exceed best possible score
|
|
35541
|
+
if (this.currentScore > this.bestPossibleScore) {
|
|
35542
|
+
return;
|
|
35543
|
+
}
|
|
33399
35544
|
// Check whether the move already exists
|
|
33400
35545
|
const move = {
|
|
33401
35546
|
score: this.currentScore,
|
|
@@ -33426,23 +35571,27 @@ class Riddle extends BaseGame {
|
|
|
33426
35571
|
// If the move is not valid or was already played, return
|
|
33427
35572
|
if (!move)
|
|
33428
35573
|
return;
|
|
33429
|
-
const { state } = this;
|
|
35574
|
+
const { state, date, playerMoves } = this;
|
|
33430
35575
|
if (!state || !state.netskraflUserId)
|
|
33431
35576
|
return;
|
|
33432
35577
|
// Save all moves to localStorage (local backup/cache)
|
|
33433
35578
|
// Convert RiddleWord[] to IPlayerMove[] for persistence
|
|
33434
|
-
const movesToSave =
|
|
35579
|
+
const movesToSave = playerMoves.map((m) => ({
|
|
33435
35580
|
score: m.score,
|
|
33436
35581
|
word: m.word,
|
|
33437
35582
|
coord: m.coord,
|
|
33438
35583
|
timestamp: m.timestamp,
|
|
33439
35584
|
}));
|
|
33440
|
-
saveLocalMoves(state.netskraflUserId,
|
|
35585
|
+
saveLocalMoves(state.netskraflUserId, date, movesToSave);
|
|
33441
35586
|
// If the move does not improve the personal best, we're done
|
|
33442
35587
|
if (move.score <= this.personalBestScore)
|
|
33443
35588
|
return;
|
|
33444
35589
|
// This is the best score we've seen yet
|
|
33445
35590
|
this.personalBestScore = move.score;
|
|
35591
|
+
// If this is not today's riddle, do not submit to server
|
|
35592
|
+
const today = timestamp.split('T')[0];
|
|
35593
|
+
if (date !== today)
|
|
35594
|
+
return;
|
|
33446
35595
|
// Submit to server; the server handles all Firebase updates
|
|
33447
35596
|
// (achievements, stats, global best, leaderboard)
|
|
33448
35597
|
this.submitRiddleWord(move);
|
|
@@ -33450,11 +35599,19 @@ class Riddle extends BaseGame {
|
|
|
33450
35599
|
updateGlobalBestScore(best) {
|
|
33451
35600
|
// Update the global best score, typically as a result
|
|
33452
35601
|
// of a Firebase notification from the server
|
|
35602
|
+
// Ignore if score exceeds best possible score
|
|
35603
|
+
if (best.score > this.bestPossibleScore) {
|
|
35604
|
+
return;
|
|
35605
|
+
}
|
|
33453
35606
|
this.globalBestScore = best;
|
|
33454
35607
|
}
|
|
33455
35608
|
updateGroupBestScore(best) {
|
|
33456
35609
|
// Update the group best score, typically as a result
|
|
33457
35610
|
// of a Firebase notification from the server
|
|
35611
|
+
// Ignore if score exceeds best possible score
|
|
35612
|
+
if (best.score > this.bestPossibleScore) {
|
|
35613
|
+
return;
|
|
35614
|
+
}
|
|
33458
35615
|
this.groupBestScore = best;
|
|
33459
35616
|
}
|
|
33460
35617
|
recreateWordOnBoard(word, startCoord) {
|
|
@@ -33718,8 +35875,8 @@ class Model {
|
|
|
33718
35875
|
this.state = state;
|
|
33719
35876
|
this.isExplo = state.isExplo;
|
|
33720
35877
|
this.maxFreeGames = state.isExplo ? MAX_FREE_EXPLO : MAX_FREE_NETSKRAFL;
|
|
33721
|
-
//
|
|
33722
|
-
|
|
35878
|
+
// Initialize localized text messages from the embedded messages.json
|
|
35879
|
+
initMessages(state.locale);
|
|
33723
35880
|
}
|
|
33724
35881
|
// Simple POST request with JSON body (most common case)
|
|
33725
35882
|
async post(url, body) {
|