Wikicesty cswikivoyage https://cs.wikivoyage.org/wiki/Hlavn%C3%AD_strana MediaWiki 1.47.0-wmf.3 first-letter Média Speciální Diskuse Uživatel Diskuse s uživatelem Wikicesty Diskuse k Wikicestám Soubor Diskuse k souboru MediaWiki Diskuse k MediaWiki Šablona Diskuse k šabloně Nápověda Diskuse k nápovědě Kategorie Diskuse ke kategorii TimedText TimedText talk Modul Diskuse k modulu Podujatie Diskusia k podujatiu Brno 0 228 22105 21492 2026-05-20T12:19:31Z LiMr 96 /* Pravidelné akce */ typo 22105 wikitext text/x-wiki {{Pagebanner|Brno - panorama I - 2012.jpg|Panoramatický pohled na přibližně jihozápadní čtvrtinu města|unesco_whs=yes}} '''Brno''' je město v [[Jihomoravský kraj|Jihomoravském kraji]], největší město [[Morava|Moravy]] a druhé největší město [[Česko|České republiky]]. Je kulturním centrem Moravy a sídlem množství institucí. K nejvýznamnějším dominantám města patří hrad a pevnost ''Špilberk'' na stejnojmenném kopci a ''katedrála svatého Petra a Pavla'' na vršku ''Petrov'', utvářející charakteristické panorama města. Druhým dochovaným hradem na území Brna je ''Veveří'', kdysi vybudovaný nad řekou Svratkou a dnes se tyčící nad Brněnskou přehradou. Významnou památkou meziválečné architektury je funkcionalistická ''vila Tugendhat'', patřící mezi [[Seznam světového dědictví UNESCO|Světové dědictví UNESCO]]. V Brně se nachází celkem 14 národních kulturních památek. Historické městské jádro bylo vyhlášeno městskou památkovou rezervací. Na území města se také nachází dvě městské památkové zóny, jedna vesnická památková zóna a jedna archeologická památková rezervace. K turisticky atraktivním lokalitám patří také Chráněná krajinná oblast [[Moravský kras]], jejíž nejjižnější část zasahuje na území města. == Dálková doprava == === Letecká doprava === {{Bod|wikidata=Q748848}} Letiště Brno-Tuřany je mezinárodní letiště nacházející se 7,5&nbsp;km jihovýchodně od centra Brna. V roce 2020 nabízí společnost Ryanair pravidelné letecké spojení na tato letiště: * [[Londýn]]/Stansted – Spojené království Velké Británie a Severního Irska * Milán/Bergamo – [[Itálie]] * [[Berlín]]-Schönefeld – [[Německo]] Brněnské letiště je obsluhováno městskou hromadnou dopravou, v denní dobu autobusovou linkou E76 a v noční dobu autobusovou linkou N89. Autobus odjíždí od železničního hlavního nádraží v centru města. Interval mezi spojky činí v denní dobu 30 minut a v noční dobu 60 minut. Cena jízdného pro dospělou osobu je {{CZK|25}}, dětské jízdné je {{CZK|12}}. Pro cestu do Brna z jiných destinací lze použít větší letiště ve [[Vídeň|Vídni]], [[Praha|Praze]] či [[Bratislava|Bratislavě]], případně z menších letišť v okolí [[Ostrava|Ostravu]], [[Pardubice]] či [[Katovice]]. === Železniční doprava === {{Bod|wikidata=Q921772|popis=[https://www.cd.cz/assets/dalsi-sluzby/sluzby-ve-stanici/brno-hlavni-nadrazi.pdf plánek], [http://provoz.szdc.cz/tabule/StationDetail.aspx?lang=cs&id=5433295&t=2 tabule aktuálních odjezdů]}} Nejdůležitějším uzlem je ''Brno hlavní nádraží'', které leží u jihovýchodního okraje historického centra v sousedství hlavního tramvajového uzlu. Vede z něj sedm tratí a přímá spojení jsou: * [[w:Železniční trať Brno – Česká Třebová|tratí na Českou Třebovou]] do [[Blansko|Blanska]], [[Česká Třebová|České Třebové]] a pak dále [[w:První železniční koridor|prvním železničním koridorem]] do [[Pardubice|Pardubic]], [[Kolín]]a a [[Praha|Prahy]], [[Ústí nad Labem|Ústí na Labem]] a [[Drážďany|Drážďan]] * [[w:Železniční trať Brno–Jihlava|tratí na Jihlavu]] do [[Třebíč]]e a [[Jihlava|Jihlavy]] * [[w:Železniční trať Brno – Moravské Bránice – Hrušovany nad Jevišovkou/Oslavany|tratí na Hrušovany a Oslavany]] do [[Oslavany|Oslavan]], [[Moravský Krumlov|Moravského Krumlova]] a [[Hrušovany nad Jevišovkou|Hrušovan nad Jevišovkou]] * [[w:Železniční trať Havlíčkův Brod – Kúty|tratí z Havlíčkova Brodu do Kút]] na západ do [[w:Žďár nad Sázavou|Žďáru nad Sázavou]], [[Přibyslav]]i a [[Havlíčkův Brod|Havlíčkova Brodu]] a na východ do [[Břeclav]]i a následně na [[Slovensko]] do [[Trnava|Trnavy]] nebo [[Bratislava|Bratislavy]]. * [[w:Železniční trať Brno–Přerov|tratí do Přerova]] do [[Přerov]]a * [[w:Vlárská dráha|Vlárskou drahou]] do [[Slavkov u Brna|Slavkova u Brna]], [[Kyjov]]a, [[Bzenec|Bzence]], [[Veselí nad Moravou]] a dále až na Slovensko do [[Trenčianská Teplá|Trenčianské Teplé]]. === Autobusová doprava === {{Bod|wikidata=Q17489136}} Autobusové nádraží v Brně, známé jako Autobusové nádraží Zvonařka, je jedním z nejdůležitějších dopravních uzlů na Moravě. Nachází se asi 15 minut od hlavního vlakového nádraží a centra města. Zvonařka slouží jako klíčový uzel pro meziměstskou a mezinárodní autobusovou dopravu. Autobusy odsud jezdí nejen do mnoha měst v České republice (např. Praha, Ostrava, [[Olomouc]]), ale i do zahraničí (např. [[Vídeň]], Bratislava, [[Budapešť]]). === Autem === Vzdálenosti z vybraných měst: * [[Olomouc]] – 80 km, 0:55 h * [[Zlín]] – 100 km, 1:10 h * [[Bratislava]] – 130 km, 1:25 h * [[Vídeň]] – 140 km, 1:45 h * [[Pardubice]] – 140 km, 2:15 h * [[Hradec Králové]] – 150 km, 2:20 h * [[Ostrava]] – 170 km, 1:45 h * [[Praha]] – 210 km, 2:10 h * [[České Budějovice]] – 220 km, 2:30 h Dálnice D1 v úseku kolem Brna není zpoplatněná, konkrétně úsek Kývalka – Holubice (182-210 km). == Místní doprava == Pro dopravu po Brně se využívají nejčastěji tramvaje (v Brně často nazývány šaliny), trolejbusy a autobusy. Centrálním místem je nástupiště u hlavního vlakového nádraží. === Jízdenky === ==== Pomocí platební karty ==== Nejpohodlněji je možné koupit jízdenku pomocí platební karty přímo v dopravním prostředku prostým přiložením karty a to bez nutnosti předchozí registrace. Tento systém se jmenuje [https://www.pipniajed.cz/ Pípni a jeď!]. Na jednu platební kartu je možné zakoupit jízdenky i pro více cestujících. ==== SMS jízdenky ==== * Pro jízdenku za 20 Kč s platností 20 minut do textové zprávy napište BRNO20. * Pro jízdenku za 29 Kč s platností 75 minut do zprávy napište BRNO. * Pro jízdenku za 99 Kč s platností 24 hodin do zprávy napište BRNOD. Text odešlete na telefonní číslo 90206. SMS jízdenka vám přijde do dvou minut, při nástupu do vozu je nutné mít již jízdenku v mobilu. SMS jízdenky platí v tramvajích, trolejbusech a autobusech, naopak je nelze využít ve vlacích. Pro jejich nákup je nutná aktivace služby Premium SMS u mobilního operátora a česká mobilní SIM karta. Aktuální ceny a další možnosti nákupu jízdenek pomocí telefonu jsou na webu [https://www.dpmb.cz/jizdenky-v-mobilu#sms DPMB]. == Co vidět == {{Mapa|49.195278|16.608333|zoom=12|width=400|height=400}} === Památky === {{Bod|wikidata=Q118256}} <!--Špilberk--> {{Bod|wikidata=Q439347}} <!--Stará radnice--> {{Bod|wikidata=Q457453}} <!--vila Tugendhat--> {{Bod|wikidata=Q9374731|popis=Architekt Ernst Wiesner navrhl vilu pro brněnského textilního továrníka Alfreda Stiassniho v letech 1927–1929}} <!--Vila Stiassny--> {{Bod|wikidata=Q5037118|popis=Klášter kapucínů}} <!--Kapucínská hrobka--> {{Bod|wikidata=Q4971773}} <!--Kostnice u sv. Jakuba--> {{Bod|wikidata=Q12037699|popis=Dříve označovaný jako Mincmistrovský sklep}} <!--Sklep pod Novou radnicí--> {{Bod|wikidata=Q6467737|typ=see}} <!--Podzemí pod Zelným trhem--> {{Bod|wikidata=Q921344|cena={{CZK|50-210}}}} <!--Hrad Veveří--> {{Bod|wikidata=Q12039319|popis=Z důvodu rekonstrukce uzavřena|aktualizováno=2024-10-14}} <!--Měnínská brána--> {{Bod|wikidata=Q24352771|popis=Tři bývalé vodojemy vybudované ve druhé polovině 19. století, ulice Tvrdého (vstup brankou vedle domu č. 15)|cena={{CZK|350}}, zlevněné vstupné {{CZK|250}}|typ=see}} <!--Vodojemy na Žlutém kopci--> {{Bod|wikidata=Q102347068|popis=Roh ulice Husova a Nádražní (vchod z ulice Husova)|otevřeno=neděle po předchozí online rezervaci|cena={{CZK|150}}, děti, studenti, senioři, ZTP {{CZK|90}}|aktualizováno=2024-10-14}} <!--Kryt Denis--> {{Bod|wikidata=Q4414992|popis=Expozice o dějinách osídlení Moravy, genetika a vývoj člověka, galerie obrazů Zdeňka Buriana|cena={{CZK|120}}, snížená: {{CZK|70}}, rodinná: {{CZK|250}}}} <!--Pavilon Anthropos--> ==== Sakrální stavby ==== {{Bod|wikidata=Q45033}} <!--katedrála svatého Petra a Pavla--> {{Bod|wikidata=Q1149587}} <!--kostel svatého Jakuba Staršího--> {{Bod|wikidata=Q11062049}} <!--Bazilika Nanebevzetí Panny Marie--> {{Bod|wikidata=Q9188202|popis=Pravoslavný chrám}} <!--Pravoslavný chrám sv. Václava--> <gallery> File:Hrad Špilberk v Brně.jpg|Hrad Špilberk File:Brno, katedrála sv. Petra a Pavla.jpg|Katedrála sv. Petra a Pavla File:Brno, Radnická Stará radnice.jpg|Stará radnice File:Vila Tugendhat.jpg|Vila Tugendhat File:Brno - Church of the st. Jacob (Kostel sv. Jakuba) 1.JPG|Kostel sv. Jakuba File:Mesto Brno - Kostnice pod kostelem sv. Jakuba 1.jpg|Kostnice u sv. Jakuba File:Brno, Mincmistrovský sklep, chodba.jpg|Mincmistrovský sklep File:Brno, podzemí pod Zelným trhem (9).JPG|Labyrint pod Zelným trhem File:Bazilika Nanebevzetí Panny Marie (Brno).JPG|Bazilika Nanebevzetí Panny Marie File:Hrad Veveří - letecký pohled 05 upraveny.jpg|Hrad Veveří File:Brno chrám sv. Václava celý 7.jpg|Pravoslavný chrám sv. Václava File:Brno, Orlí, Měnínská brána (2013; 01).jpg|Měnínská brána File:Brno - pavilon Anthropos.jpg|Vstup do pavilonu Anthropos </gallery> == Kam jít == === Kina === {{Bod|wikidata=Q20052680}} <!--Kino Art--> {{Bod|wikidata=Q20057638}} <!--Kino Lucerna--> {{Bod|wikidata=Q8848601}} <!--Kino Cinema City Velký Špalíček--> {{Bod|wikidata=Q130529927}} <!--Cinema City Olympia--> ==== Letní kina ==== {{Bod|49.1931328|16.6057150|název=Letní kino Brno-střed|typ=do|adresa=Dominikánská 2, 602 00 Brno|facebook=kinobude.cz|web=https://kinobude.cz/letnikino.brnostred/|instagram=letnikino.brnostred|youtube=UCFxZIDi4bba1L9oirOAJO2g|platba=hotově|cena={{CZK|140}}}} {{Bod|49.1940536|16.6006608|název=Letní kino Špilberk|type=do|adresa=Špilberk 1, 662 24 Brno|facebook=LetniKinoSpilberk|telefon=+420 732 565 202|web=http://www.letnikinospilberk.cz/|instagram=letnikinospilberk|otevírací doba=červen-červenec od 21:30, srpen od 21:00|cena=dospělí {{CZK|120}}, studenti {{CZK|100}}, děti do 12 let zdarma}} === Divadla === {{Bod|wikidata=Q1138893}} <!--Mahenovo divadlo--> {{Bod|wikidata=Q3511873}} <!--Janáčkovo divadlo--> {{Bod|wikidata=Q578426|název=Městské divadlo Brno|web=https://mdb.cz/|adresa=Lidická 16, 602 00 Brno|telefon=+420 533 316 320|email=komercni@mdb.cz}} <!--Městské divadlo Brno - je správná položka wikidat?--> {{Bod|wikidata=Q660777}} <!--Divadlo Reduta--> {{Bod|wikidata=Q12034015|název=Divadlo Radost|web=https://divadlo-radost.cz/|komentář=divadlo pro děti a mládež, představení loutková i s živými herci}} <!--Divadlo Radost--> {{Bod|wikidata=Q12016576}} <!--Divadlo na Orlí--> {{Bod|wikidata=Q11812406|název=Divadlo Bolka Polívky|web=https://divadlobolkapolivky.cz/}} <!--Divadlo Bolka Polívky--> {{Bod|wikidata=Q11812413|název=Divadlo Husa na provázku|web=https://www.provazek.cz/}} <!--Divadlo Husa na provázku--> === Další === {{Bod|wikidata=Q12021065|název=Hvězdárna a planetárium Brno}} <!--Hvězdárna a planetárium Brno--> {{Bod|wikidata=Q10861305|cena=vstupné (březen-říjen/listopad-únor): {{CZK|180}}/{{CZK|130}}, senioři, studenti a děti: {{CZK|120}}/{{CZK|90}}, rodinné: {{CZK|480}}/{{CZK|350}}, pes: {{CZK|100}}}} <!--Zoo Brno--> {{Bod|wikidata=Q121084826|cena=vstupné: {{CZK|180}}, děti: {{CZK|120}}, rodinné: {{CZK|450}}}} <!--Papilonia Brno--> === Noční život === {{Bod|název=Two Faces|typ=drink|49.1920708|16.6060189|web=http://www.twofaces.cz|adresa=Biskupská 1, 602 00 Brno|telefon=+420 775 960 930|email=club@twofaces.cz|komentář=taneční a noční klub}} {{Bod|název=Tabarin Club & Bar|typ=drink|49.1948875|16.6142128|web=http://www.tabarin.cz|adresa=Divadelní 603/3, 602 00 Brno|email=tabarin@tabarin.cz|facebook=TabarinClub|instagram=tabarinclub|komentář=taneční a noční klub}} {{Bod|wikidata=Q15304231|typ=drink|komentář=hudební klub, moderní kulturní centrum, ve kterém se konají koncerty, taneční večery, divadelní představení a různé festivaly}} {{Bod|wikidata=Q12027647|typ=drink|komentář=hudební, divadelní a filmový klub}} <!--Kabinet múz--> {{Bod|název=Metro Music Bar|typ=drink|49.1947364|16.6100858|web=https://www.metromusic.cz|adresa=Poštovská 450/6, 602 00 Brno|telefon=+420 515 533 452|email=production@metromusic.cz|facebook=metromusic|instagram=metromusicbar|komentář=hudební a taneční klub zaměřený na jazz, funk, blues a rock, často s živou hudbou|otevírací doba=ÚT-SO 19:00-05:00, PO a NE zavřeno}} {{Bod|wikidata=Q130526608|typ=drink|komentář=hudební klub, otevřeno dle programu}} <!--Melodka--> {{Bod|název=Cabaret des Péchés|typ=drink|49.1943581|16.6062444|web=https://www.cabaretdespeches.com|adresa=Palác Jalta, Dominikánského náměstí 656/2, 602 00 Brno|telefon=+420 774 497 277|email=info@cabaretdespeches.com|facebook=cabaretdespeches|instagram=cabaretdespeches|komentář=kabaretní, burleskní, hudební, kouzelnická představení a komediální show|otevírací doba=ÚT-SO 18:00-02:00, PO a NE zavřeno}} {{Bod|název=Artbar|typ=drink|49.2079586|16.6037942|web=https://www.artbar.club|adresa=Štefánikova 836/1, 602 00 Brno|telefon=+420 721 850 166|facebook=artbarmusicclub|instagram=artbar.club|komentář=koncerty, výstavy, divadelní představení, filmové projekce, literární večery a diskusní setkání, interiér zdobený výtvarnými díly|popis=Vstup z ul. Kotlářská}} {{Bod|wikidata=Q130896103|typ=drink|komentář=menší multižánrový hudební a kulturní klub pořádající koncerty, filmové projekce, literární večery, diskuse a tematické párty}} <!--Klub Alterna--> {{Bod|wikidata=Q96460947|typ=drink|komentář=hudební klub podporující místní a zahraniční umělce, koncerty od folku a jazzu po alternativní a experimentální hudbu, divadelní inscenace a autorské čtení}}<!--Klub Leitnerova--> === Pravidelné akce === {{Bod|wikidata=Q545584|komentář=mezinárodní soutěž ohňostrojů, které jsou synchronizovány s hudbou|frekvence=každoročně|místo=Brněnská přehrada|web=https://www.ignisbrunensis.cz|měsíc=červen|youtube=UC9meqUFQ8k70KakEa_WGFiQ|cena=volný vstup}} {{Bod|49.2002211|16.6078411|typ=do|název=Kultura pod hvězdami|komentář=letní celorepubliková kulturní akce, která zahrnuje, letní kina, muzikály, divadelní, pěvecké a taneční vystoupení, koncerty, výstavy, které se odehrávají pod širým nebem na různých místech v Brně|frekvence=každoročně|web=https://www.kulturapodhvezdami.cz/cs/program?mesto=brno|měsíc=červenec-srpen|telefon=+420 730 111 866|facebook=kulturapodhvezdami|instagram=kulturapodhvezdami|youtube=UChQTcfYKb80NnOqStYxGxaQ|cena=volný vstup}} {{Bod|49.1931583|16.6085561|typ=do|název=Uprostřed|komentář=multižánrový festival uprostřed Brna náměstí|frekvence=každoročně|web=https://festivaluprostred.cz/|měsíc=červen-srpen|místo=nádvoří Staré radnice, Moravské náměstí, Římské náměstí, Denisovy sady|cena=volný vstup|telefon=+420 542 427 150|facebook=|instagram=|email=info@ticbrno.cz}} {{Bod|49.1943303|16.5996214|typ=do|název=Letní Shakespearovské slavnosti|komentář=divadelní přehlídka her pod širým nebem zaměřená na uvádění děl Williama Shakespeara|frekvence=každoročně|web=https://brno.shakespeare.cz/|měsíc=červenec-srpen|telefon=|facebook=|instagram=|email=info@ticbrno.cz}} {{Bod|49.1996192|16.6063089|typ=do|název=Brazil fest Brno|komentář=festival brazilské kultury, karneval, koncerty, hudba, tanec, show, gastro zážitky|frekvence=každoročně|web=https://www.brasilfestbrno.cz/|měsíc=srpen|místo=nádvoří Staré radnice, Moravské náměstí, Červený kostel, nám. Svobody, Jakubské náměstí, park Lužánky|cena=volný vstup|telefon=|facebook=|instagram=|email=info@ticbrno.cz}} {{Bod|49.1902886|16.5938131|typ=do|název=Mendel festival|komentář=open air festival, hudební a populárně-vědecký program|frekvence=každoročně|web=https://brno.shakespeare.cz/|měsíc=červenec|cena=volný vstup|facebook=mendelfestival|instagram=mendelfestival}} {{Bod|49.1847011|16.5798281|typ=do|název=Pop Messe|komentář=festival soudobé populární a alternativní hudby|frekvence=každoročně|web=https://popmesse.cz/|telefon=+420 511 112 504|email=info@popmesse.cz|měsíc=červenec|cena={{CZK|1750}}|facebook=popmessefestival|instagram=pop_messe|youtube=UCO-gTW1SNeCSlMMmZfRUJ-A|tiktok=pop_messeis}} {{Bod|49.2557478|16.4588231|typ=do|název=Festival Hrady CZ|komentář=letní hudební a kulturní festival|frekvence=každoročně|web=https://www.hradycz.cz/|měsíc=srpen|místo=Hrad Veveří|cena=od {{CZK|1250}}|telefon=+420 736 128 736|facebook=CESKEHRADY|instagram=hradycz|tiktok=hradycz|youtube=UC1KwEzuBC9KVoOahejoDCPg|email=info@nedomysleno.cz}} {{Bod|49.1952669N|16.6073183|typ=do|název=Brněnské vánoce|komentář=vánoční trhy, kulturní program, koncerty, dílny pro děti i dospělé|frekvence=každoročně|web=https://brnenskevanoce.cz/|měsíc=prosinec|místo=náměstí Svobody,Dominikánské náměstí, Zelný trh, Moravské náměstí a nádvoří Staré radnice|cena=volný vstup|facebook=brnenskevanoce|instagram=brnenskevanoce|tiktok=|youtube=|email=info@ticbrno.cz}} == Kde spát == V Brně je přes 10 000 lůžek v hotelích, penzionech, hostelech, ubytovnách a apartmánech. Přinášíme výběr ubytovacích zařízení v centru města a jeho blízkém okolí. === Hotely ★★★★★ === {{Bod|wikidata=Q115430910}} {{Bod|název=Grandezza Hotel Luxury Palace|49.1924006N|16.6096886E|typ=sleep|adresa=Zelný trh 314/2, 602 00 Brno|web=https://www.grandezzahotel.com/|telefon=+420 542 106 010|mobil=+420 603 888 789|email=info@grandezzahotel.cz|platba=hotově, bankovní kartou|facebook=100063639666620|instagram=grandezzahotel}} === Hotely ★★★★ === {{Bod|wikidata=Q30445219}} <!--Hotel Continental--> {{Bod|wikidata=Q15696494|název=Hotel International}} {{Bod|49.1926489|16.6071361|název=Hotel Royal Ricc|adresa=Starobrněnská 338/10, 602 00 Brno-střed|typ=sleep|web=https://www.royalricc.cz|telefon=+420 542 219 262|mobil=+420 736 487 948|fax=+420 542 219 265|email=rezervace@royalricc.cz|facebook=RoyalRicc|instagram=hotelroyalricc|cena=od {{CZK|3551}}}} {{Bod|wikidata=Q30793114|typ=sleep|cena=od {{CZK|2892}}}} === Hotely ★★★ === {{Bod|wikidata=Q37815141|název=Hotel Pegas}} <!--Hotel Pegas--> {{Bod|název=VV Hotel|49.19082467745717|16.615932047529807|typ=sleep|adresa=Mlýnská 8a, 602 00 Brno|web=https://www.vvhotel.cz/|telefon=+420 732 558 439|email=info@vvhotel.cz}} {{Bod|wikidata=Q109624807|cena=od {{CZK|890}}}} {{Bod|wikidata=Q12020398|cena=od {{CZK|1899}}}} === Penziony === {{Bod|wikidata=Q126684686|cena= od {{CZK|1670}}}} === Hostely === {{Bod|wikidata=Q111116356|cena= od {{CZK|350}}}} {{Bod|název=Schrott Bed&Beer|49.1913603|16.6160114|typ=sleep|adresa=Křenová 291/10, 602 00 Brno|telefon=+420 725 750 256|checkin=15:00|checkout=11:00}} === Apartmány === {{Bod|49.1959119|16.6090611|název=Apartmánový dům Centrum|typ=sleep|adresa=Běhounská 115/4, 602 00 Brno|aktualizováno=2024-10-19|checkin=15:00|checkout=10:00|telefon=+420 533 534 154}} {{Bod|49.191439|16.616828|název=Flat in Brno|typ=sleep|adresa=Rumiště 6, 602 00 Brno|web=https://flatinbrno.cz/|aktualizováno=2024-10-19|checkin=15:00|checkout=10:00|telefon=+420 724 185 434|email=info@flatinbrno.cz}} === Ubytovny === {{Bod|49.1959983|16.6175028|název=Ubytovna Pohoda|typ=sleep|adresa=Cejl 10a, 602 00 Brno|web=https://www.ubytovna-pohoda.cz/|aktualizováno=2024-10-28|telefon=+420 777 201 803}} {{Bod|49.1939431|16.6246131|název=Ubytovna Moravan|typ=sleep|adresa=Podnásepní 375/1, 602 00 Brno|web=https://www.svomi-ubytovani.cz/ubytovani-centrum-krenova-podnasepni/|cena= od {{CZK|232}}|aktualizováno=2024-10-30|telefon=+420 604 507 030|email=accom.brno@email.cz}} == Kde jíst == {{Bod|typ=eat|název=Restaurace Padowetz|49.1913006|16.6109258|platba=hotově, bankovní kartou|aktualizováno=2024-10-30|adresa=Masarykova 413/34, 602 00 Brno|telefon=+420 734 617 456|web=https://restaurant-padowetz.cz/|email=restaurant@padowetz.cz|facebook=PadowetzOriginalRestaurant|instagram=padowetzrestaurant|otevírací doba=PO-ČT 11:00-24:00, PÁ-SO 11:00-01:00, NE 11:00-24:00}} {{Bod|typ=eat|název=Stopkova Plzeňská pivnice|49.1956619|16.6067200|komentář=česká kuchyně|platba=hotově, bankovní kartou|aktualizováno=2024-10-30|adresa=Česká 163/5, 602 00 Brno|telefon=+420 517 070 080|web=https://stopkova.kolkovna.cz/|email=info@stopkovapivnice.cz|facebook=StopkovaPivnice|instagram=kolkovna_restaurants|otevírací doba=PO-SO 11:00-24:00, NE 11:00-23:00}} {{Bod|typ=eat|název=Restaurace ZaZa|49.1956336|16.6118611|komentář=Neapolská pizza, víno, pivo|platba=hotově, bankovní kartou|aktualizováno=2024-10-30|adresa=Váchova 46/4, 602 00 Brno|telefon=+420 517 070 080|web=https://www.zazabrno.cz/|email=rezervace@zazabrno.cz |facebook=zazabrno|instagram=zazabrno|otevírací doba=PO-PÁ 16:30-23:00, SO-NE 11:30-22:00}} == Kde pít == === Bary === {{Bod|typ=drink|název=Super Panda Circus|49.1926003|16.6051831|platba=hotově, bankovní kartou|aktualizováno=2024-11-02|adresa=Šilingrovo nám. 257/3, 602 00 Brno-střed|telefon=+420 734 878 603|web=https://www.superpandacircus.cz/|popis=Vchod z ulice Husova|komentář=Originální koktejlový bar s unikátní atmosférou a kreativními drinky|email=adam@superpandacircus.cz|facebook=superpandabrno|instagram=super_panda_circus|otevírací doba=PO-ÚT 19:00-02:00, ST-SO 19:00-02:00, NE zavřeno}} {{Bod|typ=drink|název=Bar, který neexistuje|49.1958947|16.6098228|platba=hotově, bankovní kartou|aktualizováno=2024-11-02|adresa=Dvořákova 24/1, 602 00 Brno|telefon=+420 734 878 602|web=https://www.barkteryneexistuje.cz|komentář=jeden z nejznámějších barů v Brně s širokou nabídkou koktejlů a příjemnou atmosférou|email=rezervace@turbomost.cz|facebook=BarKteryNeexistuje|instagram=bar_ktery_neexistuje|otevírací doba=PO-ÚT 17:00-02:00, ST-ČT 17:00-02:30, PÁ-SO 17:00-03:30, NE 17:00-02:00}} {{Bod|typ=drink|název=4pokoje|49.1957508|16.6118183|platba=hotově, bankovní kartou|aktualizováno=2024-11-02|adresa=Vachova 45/6, 602 00 Brno|telefon=+420 770 122 102|web=https://www.miluju4pokoje.cz|komentář=moderní bar s pestrou nabídkou drinků a jídel|email=hana.vesela@lidizbaru.cz|facebook=4pokojebrno|instagram=4pokojebrno|otevírací doba=PO-ÚT 17:00-01:00, ST 17:00-03:00, ČT-SO 17:00-04:00, NE zavřeno}} === Pivnice === {{Bod|typ=drink|název=Pivní burza|49.1947461|16.6116414|platba=hotově, bankovní kartou|aktualizováno=2024-11-02|adresa=Jánská 467/16, 602 00 Brno-střed|telefon=+420 776 668 290|web=https://pivniburza.cz|komentář=zajímavý koncept, kde ceny piva kolísají jako na burze. Výborné místo pro pivní nadšence.|email=info@pivniburza.cz|facebook=pivniburza|instagram=pivniburza|otevírací doba=PO-NE 15:00-01:00}} {{Bod|typ=drink|název=Lokál U Cajpla|49.1959028|16.6094414|platba=hotově, bankovní kartou|aktualizováno=2024-11-02|adresa=Kozí 115/3, 602 00 Brno|telefon=+420 731 594 671 |web=https://lokal-ucaipla.ambi.cz/cz/|komentář=skvělé pivo a domácí jídlo|email=ucaipla@ambi.cz|facebook=lokalucaipla|instagram=lokalcz|otevírací doba=PO-ČT 11:00-24:00, PÁ-SO 11:00-01:00, NE 11:00-22:00}} {{Bod|typ=drink|název=U Dřevěného vlka|49.1928375|16.6097833|platba=hotově, bankovní kartou|aktualizováno=2024-11-02|adresa=Zelný trh 318/1, 602 00 Brno|telefon=+420 511 181 010 |web=https://www.drevenyvlk.cz/|komentář=široká nabídka piv z malých a regionálních pivovarů|email=drevenyvlk@gmail.com|facebook=drevenyvlk|otevírací doba=PO-ÚT 11:00-24:00, ST-PÁ 11:00-01:00, SO 12:00-01:00, NE 12:00-24:00}} == Nákupy a služby == === Nákupy === {{Bod|wikidata=Q11878044|popis=Obchodní centrum stojí mezi hlavním vlakovým a autobusovým nádražím. Tato obchodní galerie je v blízkosti historického centra a zahrnuje obchody, restaurace, služby, parkoviště.}} <!--Galerie Vaňkovka--> {{Bod|wikidata=Q10859380|popis=Velké nákupní centrum s desítkami obchodů, od velké Ikea až po malé butiky. Leží jižně od centra v městské části Brno-jih (zastávka Ikea nebo Avion Shopping).}} <!--Avion Shopping Park Brno--> {{Bod|wikidata=Q12042579|popis=Olympia se nachází také v Brně-jihu, samostatné čtvrti jižně od centra (autobusová zastávka "Modřice, Olympia"). Je to obrovské nákupní centrum určené pro rodiny, které zde chtějí strávit celý den. Kromě velkého množství obchodů, které se zde nacházejí, se v centru Olympia nachází také multikino, několik kaváren a restaurací (od McDonald's po Sushi bary), amfiteátr a velké dětské hřiště.}} <!--Olympia centrum--> {{Bod|wikidata=Q11707375}} <!--Campus Square--> === Půjčovny === {{Bod|typ=go|název=Autopůjčovna Smíšovský|komentář=půjčovna automobilů a dodávek|49.1223433|16.6047194|aktualizováno=2024-10-30|adresa=Brněnská 988, 664 42 Modřice|telefon=+420 608 776 900|web=https://www.smisak.cz/|cena=od {{CZK|1500}}|email=smisovsky@seznam.cz|otevírací doba=NON-STOP}} {{Bod|typ=go|název=Autopůjčovna - Comfort Car|komentář=půjčovna automobilů a pick-up|49.1819422|16.6296000|aktualizováno=2024-10-30|adresa=Černovické nábřeží 501/7a, 618 00 Brno|telefon=+420 776 463 211|web=https://www.comfort-car.cz/|cena=od {{CZK|390}}|email=info@comfort-car.cz|otevírací doba=8:00-20:00}} {{Bod|typ=go|název=Na Skútr Brno|komentář=půjčovna skútrů Honda|49.1755694|16.6397431|platba=hotově, QR|aktualizováno=2024-10-30|adresa=Faměrovo nám. 40/9, 618 00 Brno-Černovice|telefon=+420 724 185 434|web=https://www.naskutrbrno.cz|cena=od {{CZK|950}}|email=pujcovna@naskutrbrno.cz|otevírací doba=8:00-16:00}} == Kam dál == * [[Moravský kras]] - největší a nejlépe vyvinutá krasová oblast s nejširším spektrem krasových jevů v České republice, sousedí s Brnem == Externí odkazy == * {{Wikipedie}} * [https://www.ticbrno.cz/ Turistické informační centrum Brno] [[Kategorie:Jihomoravský kraj]] [[Kategorie:Města v Česku]] o3v0ntcs2omc8k94kf80v4fdbmmkv8p Modul:Mapshape utilities/i18n 828 1317 22107 17674 2026-05-20T12:33:10Z LiMr 96 aktualizace na novější verzi 22107 Scribunto text/plain -- kopie z německých wikicest (https://de.wikivoyage.org/w/index.php?title=Modul:Mapshape_utilities/i18n&oldid=1735601) -- copy from dewikivoyage (https://de.wikivoyage.org/w/index.php?title=Modul:Mapshape_utilities/i18n&oldid=1735601) return { -- module administration moduleInterface = { suite = 'Mapshape utilities', sub = 'i18n', serial = '2025-12-21', item = 65448276 }, excludeOSM = false, -- set true in case of mapserver malfunction usePropertyCategs = true, -- for Wikidata properties -- defaults defaultFill = '#555555', defaultFillOpacity = 0.5, defaultMarkerColor = '#5E74F3', defaultStroke = '#000000', defaultStrokeWidth = 2, defaultStrokeOpacity = 0.5, defaultShapesWidth = 3, defaultShapesOpacity = 0.8, defaultHeight = 420, defaultWidth = 420, defaultHighlight = '#66bb77', -- mapgroup defaultZoom = 14, defaultColors = { '#8fb6d9', '#a5c15d', '#ffb261', '#e4db5e', '#d56d76', '#a8a567', '#80bb89', '#b569b5' }, maxZoomLevel = 19, -- copy from Module:Marker utilities/i18n borderAdjustment = 2, -- borders inside maps -- type defaults for map shapes defaultGroup = 'mask', -- Properties for set of mapshapes -- P527: has part -- P1535: used by -- P2670: has parts of the class mapshapesProps = { 'P527', 'P2670', 'P1535', 'P121' }, -- strings geomask = 'Maskování %s', mapOf = '%s na mapě', -- maintenance mfBadData = 'Nesprávné souřadnice.', mfErrorCateg = '[[Kategorie:Údržba:Chyby map]]', mfExactlyOne = 'Bod se skládá pouze z jedné souřadnice.', mfMinValues = 'Každá skupina souřadnic musí mít alespoň %d hodnot.', mfNoCommons = 'Nebyl specifikován soubor Commons.', mfNoParts = 'V datové sadě Wikidata nejsou žádné podřízené prvky.', mfNoService = 'Žádný nebo nesprávný typ obrysu.', mfNoWdCoord = 'Na Wikidatech nejsou k dispozici žádné souřadnice.', mfNoWikidata = 'Nebyl zadán žádný identifikátor Wikidat.', mfTogether = '<span class="error">Mapa: Wikidata a parametry souřadnic nelze používat současně.</span>[[Kategorie:Údržba:Chyby map]]', mfTogether2 = '<span class="error">Mapa: Parametry wikidata a wikicommons nelze používat současně.</span>[[Kategorie:Údržba:Chyby map]]', mfTooManyLevels = 'Příliš mnoho úrovní.', mfUnknown = '[[Kategorie:Údržba:Chyby map]]', -- mfWithShapes = '[[Kategorie:Mapframe: Mit Mapshapes]]', --myslím že není třeba kategorizovat mfFromCommons = '[[Category:Mapframe: Kartendaten aus Wikimedia Commons]]', msMissing = '<span class="error">Mapa: Musí být zadán parametr wikidata nebo commons.</span>[[Kategorie:Údržba:Chyby map]]', msTogether = '<span class="error">Mapa: Parametry wikidata a wikicommons nelze používat současně.</span>[[Kategorie:Údržba:Chyby map]]', msUnknown = '<span class="error">Mapa: Neznámé parametry.</span>[[Kategorie:Údržba:Chyby map]]', mssMissingFirst = '<span class="error">Mapa: Parameter 1 chybí.</span>[[Kategorie:Údržba:Chyby map]]', mssNoChilds = '<span class="error">V datové sadě Wikidata nejsou žádné podřízené prvky.</span>[[Kategorie:Údržba:Chyby map]]', mssUnknown = '<span class="error">Mapa: Neznámé parametry.</span>[[Kategorie:Údržba:Chyby map]]', properties = '[[Kategorie:Monitoring:Data z wikidat]]', unknownParam = ' <span class="error">Neznámý parametr: %s</span>', unknownParams = ' <span class="error">Neznámé parametry: %s</span>' } lae4q93211f7msuy44y13pcrg10hu5i Modul:Wikidata utilities 828 1320 22104 17190 2026-05-20T12:16:53Z LiMr 96 aktualizace na novější verzi 22104 Scribunto text/plain -- Wikidata convenience utilities -- kopie z německých wikicest (https://de.wikivoyage.org/w/index.php?title=Modul:Wikidata_utilities&oldid=1775622) -- copy from dewikivoyage (https://de.wikivoyage.org/w/index.php?title=Modul:Wikidata_utilities&oldid=1775622) -- documentation local WikidataUtilities = { suite = 'WikidataUtilities', serial = '2026-05-17', item = 65439025 } -- i18n local wd = { version = 'P348', startTime = "P580", endTime = "P582", retrieved = 'P813', gregorianCalendar = { -- calendar models Q12138 = 1, -- Gregorian Q1985727 = 1 -- proleptic Gregorian }, redirectBadges = { Q70894304 = 1, -- intentional sitelink Q70893996 = 1 -- redirect sitelink } } -- module variable and administration local wu = { moduleInterface = WikidataUtilities, currentTime = '' } -- table storing property ids used local catTable = { P0 = '' } local function isSet( arg ) return arg and arg ~= '' end function wu.getEntity( id ) local wrongQualifier = false local entity = nil if not isSet( id ) then return '', entity, wrongQualifier end if mw.wikibase.isValidEntityId( id ) then -- expensive function call -- redirect ids marked false, too entity = mw.wikibase.getEntity( id ) end if not entity then id = '' wrongQualifier = true end return id, entity, wrongQualifier end function wu.getEntityId( id ) local wrongQualifier = false local entity if not isSet( id ) then id = '' elseif mw.wikibase.isValidEntityId( id ) and mw.wikibase.entityExists( id ) then -- expensive function call -- redirect ids marked false, too entity = id else id = '' wrongQualifier = true end return id, entity, wrongQualifier end function wu.getLabel( entity, lang, noFallback ) if not isSet( entity ) then return nil end local tp = type( entity ) if tp == 'string' and mw.wikibase.isValidEntityId( entity ) then return isSet( lang ) and mw.wikibase.getLabelByLang( entity, lang ) or ( not noFallback and mw.wikibase.getLabel( entity ) ) elseif tp == 'table' and entity.labels then -- really a wikidata entity? return isSet( lang ) and entity:getLabel( lang ) or ( not noFallback and entity:getLabel() ) end return nil end function wu.getAliases( entity, lang ) if type( entity ) == 'string' then -- is Q id entity = mw.wikibase.getEntity( entity ) end if not lang then lang = mw.getContentLanguage():getCode() end local aliases = {} if entity and entity.aliases and entity.aliases[ lang ] then for i, alias in ipairs( entity.aliases[ lang ] ) do table.insert( aliases, alias.value ) end end return aliases end function wu.getSitelink( entity, globalSiteId ) if not isSet( entity ) then return nil end if type( entity ) == 'string' then -- entity is id return mw.wikibase.getSitelink( entity, globalSiteId ) elseif entity and entity.labels then return entity:getSitelink( globalSiteId ) end return nil end local function getSitelinkTable( entity, globalSiteId ) if not isSet( entity ) or not isSet( globalSiteId ) then return nil elseif type( entity ) == 'string' then -- entity is id entity = mw.wikibase.getEntity( entity ) end if entity and entity.sitelinks then return entity.sitelinks[ globalSiteId ] end return nil end -- getting sitelink title marking as redirect function wu.getCheckedSitelink( entity, globalSiteId ) local isRedirect = false local t = getSitelinkTable( entity, globalSiteId ) if not t or not t.title then return nil, isRedirect end for i = 1, #t.badges do if wd.redirectBadges[ t.badges[ i ] ] then isRedirect = true break end end return t.title, isRedirect end -- getting sitelink title exclunding redirects function wu.getFilteredSitelink( entity, globalSiteId ) local title, isRedirect = wu.getCheckedSitelink( entity, globalSiteId ) return ( title and not isRedirect ) and title or nil end -- convert from url to Q id local function getUnitId( unit ) if isSet( unit ) and type( unit ) == 'string' then return unit == '1' and unit or unit:sub( unit:find( 'Q', 1, true ), -1 ) end return '' end local function getAmount( amount ) if amount:sub( 1, 1 ) == '+' then amount = amount:sub( 2 ) end return amount end local function getBestStatements( entity, p ) local tp = type( entity ) if tp == 'string' and mw.wikibase.isValidEntityId( entity ) then return mw.wikibase.getBestStatements( entity, p ) elseif tp == 'table' and entity.labels then return entity:getBestStatements( p ) end return {} end local function getTime( statement, p ) local q if statement and statement.qualifiers and statement.qualifiers[ p ] then q = statement.qualifiers[ p ][ 1 ] if q.snaktype == 'value' and q.datatype == 'time' then q = q.datavalue.value.time if q:sub( 1, 1 ) ~= '-' then -- B. C. return q:sub( 1, 11 ) end end end return nil end local function getStatements( entity, p, count ) local ar = {} if not ( isSet( entity ) and isSet( p ) ) then return ar end local statements = getBestStatements( entity, p ) count = math.min( count or #statements, #statements ) if count <= 0 then return ar end local i = 0 local statement, outdated, startTime, endTime repeat i = i + 1 statement = statements[ i ].mainsnak if statement.snaktype == 'value' then if statement.datatype == 'quantity' then statement.datavalue.value.amount = getAmount( statement.datavalue.value.amount ) statement.datavalue.value.unit = getUnitId( statement.datavalue.value.unit ) end startTime = getTime( statements[ i ], wd.startTime ) endTime = getTime( statements[ i ], wd.endTime ) if wu.currentTime == '' and ( startTime or endTime ) then wu.currentTime = '+' .. mw.getContentLanguage():formatDate( 'c' ):sub( 1, 10 ) end if startTime and wu.currentTime < startTime then outdated = true else outdated = endTime and wu.currentTime > endTime end if not outdated then table.insert( ar, statements[ i ] ) end end until i >= #statements or #ar >= count return ar end function wu.getValue( entity, p ) local statements = getStatements( entity, p, 1 ) if #statements > 0 then catTable[ p ] = '' return statements[ 1 ].mainsnak.datavalue.value end return '' end function wu.getId( entity, p ) local value = '' local statements = getStatements( entity, p, 1 ) if #statements > 0 then value = statements[ 1 ].mainsnak.datavalue.value value = value.id or '' if value ~= '' then catTable[ p ] = '' end end return value end function wu.getValues( entity, p, count ) local statements = getStatements( entity, p, count ) if #statements > 0 then for i = 1, #statements, 1 do statements[ i ] = statements[ i ].mainsnak.datavalue.value end catTable[ p ] = '' end return statements end function wu.getIds( entity, p, count ) local statements = getStatements( entity, p, count ) if #statements > 0 then for i = #statements, 1, -1 do statements[ i ] = statements[ i ].mainsnak.datavalue.value.id if not statements[ i ] then table.remove( statements, i ) end end if #statements > 0 then catTable[ p ] = '' end end return statements end function wu.getValuesByLang( entity, p, count, lang ) local ar = {} local statements = getStatements( entity, p ) if #statements > 0 then local value for i = 1, #statements, 1 do value = statements[ i ].mainsnak.datavalue.value if value.language and lang == value.language then table.insert( ar, value.text ) end if count and #ar >= count then break end end end if #ar > 0 then catTable[ p ] = '' end return ar end -- get values array for monolingual text function wu.getMonolingualValues( entity, p ) local result = {} local statements = getStatements( entity, p, nil ) if #statements > 0 and statements[ 1 ].mainsnak.datatype == 'monolingualtext' then local hyphen, lng, value catTable[ p ] = '' for i = 1, #statements, 1 do value = statements[ i ].mainsnak.datavalue.value lng = value.language hyphen = lng:find( '-' ) if hyphen then lng = lng:sub( 1, hyphen - 1 ) end if not result[ lng ] then result[ lng ] = value.text end end end return result end function wu.getValuesByQualifier( entity, p, qualifierP, defaultId ) local result = {} if not isSet( qualifierP ) then return result elseif type( defaultId ) ~= 'string' or defaultId == '' then defaultId = 'unknown' end local statements = getStatements( entity, p, nil ) if #statements > 0 then catTable[ p ] = '' local id, statement, value for i = 1, #statements do statement = statements[ i ] -- defaultId is used if a qualifier is missing id = defaultId value = statement.mainsnak.datavalue.value if statement.qualifiers and statement.qualifiers[ qualifierP ] then for j, qualifier in ipairs( statement.qualifiers[ qualifierP ] ) do if qualifier.snaktype == 'value' then id = qualifier.datavalue.value.id if id then catTable[ qualifierP ] = '' break end end end end result[ id ] = value end end return result end local function analyzeDatavalue( datavalue, labelFct, ... ) local v = datavalue.value local t = datavalue.type if type( v ) == 'table' then -- items which can be reduced to a string if t == 'wikibase-entityid' then v = v.id if type( labelFct ) == 'function' then v = labelFct( v, ... ) end elseif t == 'quantity' then v.amount = getAmount( v.amount ) if tonumber( v.amount ) == 0 then v.amount = '0' end if v.unit == '1' then v = tonumber( v.amount ) or 1 else v.unit = getUnitId( v.unit ) end elseif t == 'time' then v.calendarmodel = getUnitId( v.calendarmodel ) if wd.gregorianCalendar[ v.calendarmodel ] then -- is gregorian calendar? v = v.time end end end return v, t end -- for qualifiers, references -- { item1, item2, ... } : using named qualifiers/references -- {} : using no qualifiers/references -- nil : using all qualifiers/references function wu.getValuesWithQualifiers( entity, p, values, qualifiers, references, count, labelFct, ... ) local array, qual local function toQualifierTable( tab, key, qualTab, aLabelFct, ... ) local v if not tab[ key ] then tab[ key ] = {} end for i = 1, #qualTab do qual = qualTab[ i ] if qual.snaktype == 'value' then v, tab[ key .. '-type' ] = analyzeDatavalue( qual.datavalue, aLabelFct, ... ) table.insert( tab[ key ], v ) end end if #tab[ key ] == 0 then tab[ key ] = nil tab[ key .. '-type' ] = nil else catTable[ key ] = '' end end local function hasValue( tab, val ) for i = 1, #tab do if tab[ i ] == val then return true end end return false end local results = {} local statements = getStatements( entity, p, count ) if #statements == 0 then return results end local v if type( values ) == 'table' and #values > 0 then for i = #statements, 1, -1 do v = statements[ i ].mainsnak.datavalue.value if type( v ) ~= 'string' then v = v.id end if not isSet( v ) or not hasValue( values, v ) then table.remove( statements, i ) end end if #statements == 0 then return results end end catTable[ p ] = '' if type( qualifiers ) == 'string' then qualifiers = { qualifiers } end if type( references ) == 'string' then references = { references } end local reference, statement for i = 1, #statements do statement = statements[ i ] array = { value = analyzeDatavalue( statement.mainsnak.datavalue, labelFct, ... ), [ 'value-type' ] = statement.mainsnak.datavalue.type } if statement.qualifiers then if not qualifiers then -- all qualifier properties for key, qualTab in pairs( statement.qualifiers ) do toQualifierTable( array, key, qualTab, labelFct, ... ) end else -- table of selected qualifier properties local key for j = 1, #qualifiers do key = qualifiers[ j ] if statement.qualifiers[ key ] then toQualifierTable( array, key, statement.qualifiers[ key ], labelFct, ... ) end end end end array.references = {} if statement.references then for k = 1, #statement.references do reference = statement.references[ k ] if reference and reference.snaks then table.insert( array.references, {} ) if not references then -- all references for key2, refTab in pairs( reference.snaks ) do toQualifierTable( array.references[ #array.references ], key2, refTab ) end else -- table of selected references local key for j = 1, #references do key = references[ j ] if reference.snaks[ key ] then toQualifierTable( array.references[ #array.references ], key, reference.snaks[ key ] ) end end end end end end table.insert( results, array ) end -- clustering statements with identical value local helper = {} local sort1 = 0 local mult = false local result for i = 1, #results do result = results[ i ] if helper[ result.value ] then helper[ result.value ].sort2 = helper[ result.value ].sort2 + 1 mult = true else sort1 = sort1 + 1 helper[ result.value ] = { sort1 = sort1, sort2 = 1 } end result.sort1 = helper[ result.value ].sort1 result.sort2 = helper[ result.value ].sort2 end if sort1 > 1 and mult and #results > 2 then table.sort( results, function( a, b ) return a.sort1 < b.sort1 or ( a.sort1 == b.sort1 and a.sort2 < b.sort2 ) end ) end return results end -- extract date from time function wu.getDateFromTime( t ) local model = '' -- is Gregorian if type( t ) == 'table' then model = t.calendarmodel t = t.time end t = t:sub( 2, 11 ) return t, model end -- get lastEdit from reference retrieve date function wu.getLastedit( lastEdit, statements ) local isBoolean = type( lastEdit ) == 'boolean' if isBoolean and lastEdit == false then return lastEdit end local le = '' for i, statement in ipairs( statements ) do if statement.references then for j, reference in ipairs( statement.references ) do if reference[ wd.retrieved ] then for k, retrieved in ipairs( reference[ wd.retrieved ] ) do retrieved = wu.getDateFromTime( retrieved ) if retrieved > le then le = retrieved end end end end end end if isBoolean then return ( le ~= '' ) and le or lastEdit else return ( le > lastEdit ) and le or lastEdit end end -- maintenance utilities function wu.getCategories( formatStr ) if not isSet( formatStr ) then formatStr = '[[Category:%s]]' end catTable.P0 = nil local result = '' for key, value in pairs( catTable ) do result = result .. formatStr:format( key ) end return result end return wu ogl61n34alfole8xstr51rzb3o5e5zr Diskuse s uživatelem:OndraMix 3 1324 22113 21374 2026-05-20T13:24:12Z LiMr 96 nová sekce /* Aktualizace mapových modulů */ 22113 wikitext text/x-wiki == Šablony s mapami == Díky za založení těch mapových šablon. Zatím jsem udělal nějaké rychlé překlady z němčiny, ale mám v plánu spolupracovat ještě víc. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 4. 10. 2024, 22:30 (CEST) :Děkuju za pomoc s překlady a odchycení překlepů. Teď plánuju překládat nové moduly a založit dokumentaci k [[Šablona:Bod|šabloně Bod]]. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 5. 10. 2024, 22:40 (CEST) == Modul:Exchangerate == Už dřív založil [[Modul:Exchangerate]] z enwikivoyage. Až se mně ji podařilo přeložit a propojit úspěšně s šablonami, tak jsem narážel na nějaké problémy a sám jsem uvažoval, že přejdu na německou verzi. Teď jsi vytvořil [[Modul:Exchange rate]] z dewikivoyage. Ten jsem zkusil opět lokalizovat a napasovat na existující šablony. Teď se mně to zdá všechno funkční a čerpám i z výhod té německé verze. Předpokládám, že tu anglickou už můžeme úplně smazat. Oprávnění k tomu mám, ale chtěl bych to od někoho potvrdit. Ještě bych chtěl zmínit, že obě verze mají jeden zásadní problém. Přestože vypadají, že se kurzy automaticky aktualizují, tak ve skutečnosti byl kurz z února 2023, kdy byl naposled aktualizovaný robotem. Teď jsem to aktualizoval po roce a půl ručně. Mám v plánu to občas aktualizovat. Spíš se divím, že to tak dlouhou dobu nikomu nechybělo. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 5. 10. 2024, 23:59 (CEST) :Ten modul z enwikivoyage je na smazání. Používá se jen u [[Šablona:Kurz|šablony Kurz]], což mi přijde, že je duplicita [[Šablona:Měna|šablony Měna]]. Když už budeš mazat ten modul, tak bych tě chtěl poprosit abys smazal i článek [[Vorlage:VCard/styles.css]], který jsem založil omylem. :S těmi kurzy to je skutečně zarážející, že to nikomu tak dlouho nevadilo. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 6. 10. 2024, 00:21 (CEST) ::Tvoji žádost o smazání jsem vyřešil. ::Šablony [[:Šablona:Kurz]] a [[:Šablona:Měna]] jsou si opravdu hodně podobné. Vypadá to, že Měna je taková vyšší úroveň a má sloužit pro zapisování částek v cizích měnách např. někde v textu. Kurz obsahuje spíš různé pomocné informace. Kurz ale momentálně není nikde používaný a to ani v šabloně Měna. Přesto jsem udělal úpravy, aby byl závislý pouze na novém modulu [[Modul:Exchange rate]]. ::Omlouvám se, ale nahoře jsem to napsal blbě. Původní modul [[Modul:Exchangerate]] (včetně šablony Měna) jsem nezakládal já, ale [[:Uživatel:Polda18]]. Já jsem jen pak dělal nějaké úpravy, aby to celé lepší fungovalo. Proto bych před definitivním smazáním původního modulu počkal aspoň týden, aby měl případný čas se k tomu vyjádřit i on. Pak bych to smazal. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 6. 10. 2024, 12:06 (CEST) :::(Sorry in English) hello I'm Tmv from Japanese Wikivoyage. I will leave a note about the Exchange rate. It is a known issue that the Commons data has not been updated, as stated on the [[:de:Modul:Exchange_rate/Doku|German documentation page]]. However, at this moment we have no alternative. For this reason, some Wikivoyage communities including German and Japanese ones have chosen not to use the currency conversion feature. :::Sorry for the delay, but welcome to the Wikivoyage community! --[[Uživatel:Tmv|Tmv]] ([[Diskuse s uživatelem:Tmv|diskuse]]) 6. 10. 2024, 13:19 (CEST) :::Šablona {{tl|Kurz}} měla být používána v průvodcích týkající se země, ve které se platí danou měnou, na kterou se ten kurz vztahuje. Zakládal jsem různé technické šablony z envoy, kde se musím přiznat, že jsem se v tom sám moc nevyznal, jaký v tom měli guláš. Pokud se šablona smaže, včetně jejího modulu, tak mi to vadit zřejmě nebude. Jazyku Lua moc nerozumím, takže jsem je v podstatě jen překopíroval (s odkazem na originál samozřejmě) a doufal, že někdo technicky znalejší by to mohl přeložit a případně opravit. Těch rozbitých a polofunkčních šablon a modulů je více. [[Uživatel:Polda18|Polda18]] ([[Diskuse s uživatelem:Polda18|diskuse]]) 6. 10. 2024, 13:59 (CEST) :::Super, Modul:Exchangerate jsem smazal a jedna duplicita je pryč a máme jen [[Modul:Exchange rate]]. :::Co se týká [[:Šablona:Kurz]], tak tu zatím nechám. Zkusíme víc používat [[:Šablona:Měna]] a uvidíme, co nám bude chybět a jestli nám šablona Kurz nepomůže. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 6. 10. 2024, 15:03 (CEST) ::::Dobrá. Kdyby bylo potřeba něco upravit nebo dodělat, jsem k dispozici, určitě se můžeme na něčem domluvit. Nemám problém se případně doučit jazyk Lua, abych mohl navrhovat úpravy modulů nebo moduly nové. Pro testovací účely si mohu udělat testovací wiki na localhostu. [[Uživatel:Polda18|Polda18]] ([[Diskuse s uživatelem:Polda18|diskuse]]) 8. 10. 2024, 11:28 (CEST) == Modul:VCard/i18n - název == Vidím, že experimentuješ s názvy parametrů na svém pískovišti a něco tam nefunguje. Asi to bude tím, že jsem změnil český název parametru v Modul:VCard/i18n. Původně tam bylo "jméno" a změnil jsem to na "název". Přijde mně to vhodnější. Je spíš "název místa" než "jméno místa". I v několika dalších překladech jsem původní "name" přeložil radši jako "název". Omlouvám se, pokud jsi díky tomu ztratil čas hledáním chyby. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 6. 10. 2024, 23:18 (CEST) :Název je určitě vhodnější než jméno. Jak toho teď překládám hodně, tak si takovéto věci občas neuvědomím. Děkuju za upozornění. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 7. 10. 2024, 09:59 (CEST) == Šablona:GPX indicator == Ahoj, teď jsem zkoumal, proč pořád nefunguje [[:Šablona:GPX indicator]], která se automaticky vkládá přes [[:Šablona:Pagebanner]], ale to asi bude fungovat až tady s těmi šablonami, které se teď vytváří. Ono je to navázané přes externí tool, tak k tomu moc nejde dohledat. Tak ať víš ještě o související šabloně, která vlastně není nikde vidět, ale projeví se jako ikona GPX vpravo nahoře. Ještě procházím všechny šablony, které často ani nejsou kategorizované, takže jsou těžko dohledatelné, a dělám v nich trochu pořádek a objevuju spoustu nových ještě nepoužitých. Přemýšlím, jestli tyto nové, na kterých právě pracuješ, zařadit i do kategorie Geografických nebo ne. Sice teoreticky můžou být použité jen jako prosté seznamy bez souřadnic a map, ale v principu je bude lepší mít jednoduše mezi geografickými, protože to je jejich hlavní účel. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 9. 10. 2024, 16:21 (CEST) :Děkuju za upozornění na šablonu GPX indicator, po letmém zhlédnutí mě napadlo jestli tomu nevadí jazyk čeština. Kdyžtak na [[:de:MediaWiki:Gadget-Poi2gpx.js|německých wikicestách]] mají asi trochu jinak (nedíval jsem se na to nějak detailněji). Šablony bod i mapa bych určitě vložil do geografických šablon. Někdy o víkendu bych se podíval na tu šablonu jestli se to do té doby nepodaří vyřešit a dodělal překlady a dokumentace. Momentálně nemám moc volného času. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 9. 10. 2024, 16:54 (CEST) :Já jsem ji původně bral jako jednu z podmínek k fungování toho nového Pagebanneru, tak jsem to nezkoumal, když tam nebyla ani dokumentace. Ten jazyk jsem taky zkoušel a při změně jazyka to funguje, ale odněkud si musí vzít ta data. Není tam v podstatě nic než konkrétní URL. Podle mě to si to webserver stáhne ze zadaných wikicest, zpracuje a vrátí hotový soubor. Na tu německou verzi jsem se díval až teď a dělá to asi stejnou věc, ale technologicky úplně jinak. Na první pohled odhaduju, že soubor je vygenerovaný na straně klienta pomocí Javascriptu. Německý přístup se mně líbí víc, protože se to dá nějak přizpůsobit a není to závislé na dalších službách. Až to bude použité na reálných stránkách, tak se to může vyzkoušet. A taky jestli není lepší způsob než paušální vkládání než přes pagebanner. :Každopádně díky za super práci! Je dobré tu mít dalšího odborníka :) [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 9. 10. 2024, 17:12 (CEST) == Problémy Geo šablony == Ahoj, zkusil jsem řešit problémy, proč jsou stránky občas v této kategorii: [[:Kategorie:Stránky s nesprávnými značkami zeměpisných souřadnic]]. Může za to {{Šablona|Geo}}, ve které se uvnitř nějak špatně předávají souřadnice nebo ve špatných formátech apod. Věnoval jsem tomu už dost času a nemůžu přijít na problém. Spíš jsem hledal konkrétní problém a konkrétní opravu, ale možná jsou tam složitě použité některé šablony a moduly, nebo je potřeba je nahradit jinými. Myslím, že by tento problém mohl souviset i s jinými problémy, které se týkají souřadnic. Jestli budeš mít někdy čas, zkus se na to prosím taky podívat, jestli něco objevíš. Na testování je vhodný článek [[Zlín]], který neobsahuje další geografické šablony. Díky [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 31. 1. 2025, 13:48 (CET) :Podívám se na to. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 31. 1. 2025, 14:00 (CET) :To vypadá, že už [[:Modul:Coord]] předané souřadnice formátuje nějak jinak, než se očekává. Ale ty souřadnice se zanoří postupně do tolika modulů, že nevím, co všechno by ovlivnila jakákoliv změna. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 31. 1. 2025, 16:04 (CET) ::Myslím že jsem to nějak opravil, [[Šablona:Coord|šablona Coord]] měla odkazovat na [[Modul:Coord|modul Coord]], ale odkazovala na [[Modul:Coordinates|Coordinates]]. Tohle je jen konkrétní oprava, nerozumím teď tomu jak ty moduly formátují souřadnice. Jinak stále je u [[Šablona:Geo|šablony Geo]] peoblém že na mapě zobrazuje body z enwikivoy a na českou ji nelze přepnout, proto jsem pracoval na [[Šablona:GeoData|šabloně GeoData]], která má aktuálně ale stejnej problém. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 31. 1. 2025, 16:20 (CET) :::Mohli bychom se vrátit k těm geografickým šablonám. Poslední cíl byl teda to, že by se šablona {{Š|Geo}} nahradila šablonou {{Š|GeoData}}, aby fungovalo otvírání mapy v pravém horním roku? A pořád nevím, jestli je úspěšně přidané [[MediaWiki:Gadget-MapTools.js]], protože se to zatím nijak neprojevuje, ale má to asi pracovat s tou šablonou {{Š|GeoData}}, takže to spolu bude souviset. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 13. 3. 2025, 22:34 (CET) ::::Ahoj, ::::Můj poslední cíl bylo nahradit Geo šablonou GeoData, jelikož nevím jestli je možné, aby dobře fungovala (jak to je externí nástroj). GeoData mají aktuálně 2 problémy: nezobrazují body na mapě a neregistrují články, aby se zobrazily když vyberu ''zobrazit články v okolí'' na mapě. Snažil jsem se najít, kde je chyba ale nemůžu to najít. Momentálně mám víc jiné práce a nemám sílu hledat kde v kódu bude chyba. Určitě to nějak souvisí s tím Gadgetem, možná se snaží volat něco co není pro něj dostupné. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 14. 3. 2025, 19:02 (CET) :::::Tak nakonec mi to nedalo, našel jsem že podle [[:de:Wikivoyage:Gadget-MapTools.js|nápovědy na německých wikicestách]] gadget vyžaduje seznam článků na Wikicestách (externí) a ten pro České Wikicesty [https://wikivoyage.toolforge.org/w/data/cs-articles.js není] (zatímco německé ho [https://wikivoyage.toolforge.org/w/data/de-articles.js mají]) Je to v [[MediaWiki:Gadget-MapTools.js#L-149|řádku 149 gadgetu]] <code>(scriptUrl = mw.format( 'https://wikivoyage.toolforge.org/w/data/$1-articles.js', pageLang ),</code>), tady může vznikat nějaký problém. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 14. 3. 2025, 19:13 (CET) :::::Konečně jsem vyřešil problém s šablonou {{Šablona|Geo}}. Problém je v tom, že uvnitř tagu indicator se proměnné nepřekládají. Proto musí tento tag generován jinou šablonou. Pak to už funguje. Takže odkaz už funguje, ale samozřejmě to nevyřešilo všechny problémy. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 20. 3. 2025, 23:23 (CET) == Kategorizace == Ahoj, mám jen malou poznámku ke kategorizaci. Na Wikicestách jsou na rozdíl od Wikipedie mnohem důležitější kategorie, které upřesňují ''kde to je'' než ''co to je''. Takže jsou vhodné kategorie, které geograficky upřesňují polohu, i když ne nutně administrativní dělení na kraje (i když je to často nejpohodlnější), ale raději tradiční regiony, hory apod. Prostě když někdo někomu říká, že jede na dovolenou na Šumavu, na Slovácko, do Vysokých Tater, ... Pak možná nějaké výjimečné typy konkrétních turistických cílů, které někdo vyhledává: hrady, lázně, ... To je můj pohled na kategorie v budoucnu :) [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 15. 4. 2025, 12:21 (CEST) :Ahoj, :souhlasím s kategorizací na základě polohy, ale myslím že kategorizace na základě typu je taky důležitá. Kdyby třeba někdo hledal cíle kam jet, třeba že chce jet do hor/na hrad, tak kategorie na základě typu můžou být užitečné pro vyhledání možných cílů. Za mě by byly nejlepší kategorie typu: [(stát/kraj) (typ)], [turistické regiony]; př. Slovinská města, Julské Alpy, Triglavský národní park pro ten [[Bled]]. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 15. 4. 2025, 14:54 (CEST) == Šablona Bod v Českých Budějovicích == Ahoj, pokud bys měl čas a chuť, tak se můžeš podívat na chování {{Šablona|Bod}} v článku [[České Budějovice]]. Musel jsem tam udělat takový hack, aby se to správně zobrazovalo. Problémy jsou tam dva: * Po odrážkách jsou následující body odsazené i když by neměly být. * Bod bez souřadnic se nezalomí na nový řádek. Nebo co si myslíš o takovém použití? Resp. viděl jsem i použití šablony uprostřed textu odstavce, což překvapivě nějak fungovalo, ale oprava výše uvedených problémů by to chování mohla ovlivnit. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 14. 5. 2025, 20:31 (CEST) :Ahoj, :podívám se na to, až budu mít trochu víc času. Toho že se šablona někdy nezalomuje na další řádek jsem si už všimnul, to odrážení je pro mě novinka. :Podle mě je dobré používat bod i do souvislého textu, hlavně kvůli propojení s Wikipedií/Commons..., dodání souřadnic místa do mapy a určitého vizuálního zvýraznění místa. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 14. 5. 2025, 23:05 (CEST) :Myslím, že mám dobrý postřeh. Problém se zalomením mají dva body po sobě, u kterých není vyplněn žádný popis (možná ani nic víc za ikonami). Pěkný příklad je [[Znojmo]], konkrétně tato verze: https://cs.wikivoyage.org/w/index.php?title=Znojmo&oldid=19492, která má dokonce dvě dvojice takových případů. Přidání parametru popis do kteréhokoliv bodu vyřeší problém v dané dvojici. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 20. 5. 2025, 10:23 (CEST) == Bod a Wikicesty == Ahoj, v článku [[Šumava]] je často použita šablona {{Š|Bod}} pro jednotlivé vrcholy. Teď začalo vznikat hodně článků o těchto jednotlivých vrcholech. Šablona zobrazuje odkazy na Wikipedii, Commons, Wikidata, ..., ale vlastně vůbec neumožňuje prokliknutí na článek na Wikicestách, který by dokonce v principu měl být ten nejdůležitější. Překvapuje mně to o to víc, že podle mě ani originální německá verze toto nemá vyřešeno. Nebo je tam něco, co jsem přehlédl? [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 9. 10. 2025, 10:13 (CEST) :Ahoj, myslím že v kódu je někde ikonka pro Wikicesty zakomentovaná, jelikož dělala chyby. Podívám se na to a zkusím to nějak opravit/dodělat ji tam. Dostanu se na to nejspíš někdy o víkendu. -- [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 9. 10. 2025, 10:47 (CEST) ::Ok, díky. Když se na to ale dívám z uživatelského pohledu, tak bych očekával, že odkaz na samotném názvu by měl vést na Wikicesty. To uživatel očekává. Nevím, jestli náhodný uživatel pozná a pochopí tu správnou malou ikonku za názvem. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 9. 10. 2025, 12:58 (CEST) :::Podíval jsem se na to a teď by šablona měla zobrazovat odkaz na Wikicesty v názvu a odkaz na externí web je řešen pomocí ikonky. Momentálně je nastaveno, že jediný odkaz na externí web je přes ikonku, ale dá se upravit, aby se v případě, že neexistuje odkaz na Wikicesty, zobrazoval externí odkaz i v názvu (viz [[Modul:Marker utilities]], řádek 1476). [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 12. 10. 2025, 05:26 (CEST) ::::Tak to je super! Tak jsem si to představoval. Já jsem to teda ještě upravil tak, jak jsi sám psal. Takže je to takový hybrid mezi tím, co bylo dřív a co jsi udělal. Prostě pokud existuje na Wikicestách, tak je tam odkaz na Wikicesty, pokud ne, tak externí odkaz, nebo pokud není, tak obyčejný text. Sice je tam teď ten externí odkaz ještě i s ikonkou zeměkoule, ale myslím, že to nevadí a kvůli jednotnosti je to možná i dobře. ::::Jinak ještě nějaké technické věci: ::::* Lua používá bool hodnotu false jen s malým f, takže False byla jakoby nedefinovaná proměnná a nebylo to požadované chování. ::::* Pokud už neplánuješ nějaké další úpravy, tak bych v Modul:VCard ještě ten nový kód zjednodušil (aby byl i podobnější tomu původnímu). Zkoušel jsem to a na první pohled jsem tam neviděl problém. ::::* Ještě asi udělám aktualizace celého modulu podle nejnovější verzi na DE Wikivoyage. Snad to něco nenabourá. ::::Jsem fakt rád, že jsi to dokázal a že se aspoň občas něco zlepšuje i technicky. Díky! [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 13. 10. 2025, 12:47 (CEST) :::::Určite jen do toho, nějaké úpravy v nejbližší době neplánuji. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 13. 10. 2025, 15:24 (CEST) :::::Zjednodušení jsem udělal. A i celá aktualizace proběhla docela bez problémů. Novinkou jsou např. odkazy na mapy u šablony {{Š|Bod}}. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 14. 10. 2025, 10:34 (CEST) ::::::Výborně, s tou mapou to vypadá moc dobře. Jen jsem si všiml, že po aktualizaci zmizela ikonka Wikidat ([[Šablona:VCard/styles.css]]). Otázka je, jestli je vůbec vhodné ji tam mít – za mě je docela užitečná, protože se dá jedním kliknutím přejít na Wikidata a upravit tam, ale pro běžného čtenáře asi takový význam nemá. ::::::Další změna je, že pokud existuje článek na Wikicestách, už nejde do šablony {{šablona|Bod}} přidat web místa (viz [[Šablona:Bod/test]] → ODKAZ NA WIKICESTY → druhý odkaz na Pražský hrad nebo druhý Třístoličník). [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 14. 10. 2025, 11:04 (CEST) :::::::Já jsem věděl, že je dobré, když se na to podívá ještě někdo jiný :) Toho jsem si nevšiml a už jsem to vrátil. Byla to ruční úprava, která se aktualizací přepsala. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 14. 10. 2025, 17:06 (CEST) :::::::Tak to jsem už taky opravil. Bylo to záludné, protože právě ta tebou speciálně upravená část kódu byla přesunuta do jiného modulu a už jsem to neuhlídal. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 14. 10. 2025, 18:14 (CEST) == Šablona Geo - Zobrazit články v okolí == Podařilo se mně zase trochu vylepšit ty věci kolem šablony {{Š|Geo}}. Volám ji automaticky s parametry z Wikidat pomocí {{Š|Pagebanner}}, takže je automaticky ve všech článcích, kde je tato šablona a kde jsou definované souřadnice, tzn. fakt skoro všechny. Funguje pak i to tlačítko Zobrazit články v okolí, což je super, aby bylo vidět, které články jsou založené poblíž jiného článku. Ještě trvá problém s tím, že ikona vpravo nahoře otevře jinou mapu, kde ty články v okolí nejsou, ale na to se ještě jednou podívám. Je potřeba otevřít mapu, která je vložena pomocí šablony {{Š|Mapa}}. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 13. 10. 2025, 14:13 (CEST) :Skvělá práce, u toho {{šablona|Geo}} je problém s {{šablona|PoiMap2}}, že ten web nemá českou verzi, která by přebírala data z českých Wikicesty. Napadlo mě to obejít přes [[Modul:Mapframe|modul Mapframe]], ale momentálně na to nemám moc času. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 13. 10. 2025, 15:35 (CEST) ::Přesně to napadlo i mě. Nakonec jsem udělal samostatnou šablonu {{Š|Maplink}}, která je ale v podstatě to samé (i stejný modul). Zdá se to být funkční a asi to tak nechám. Chtěl jsem to ještě nějak vizuálně vylepšit, ale moc mně to nejde. Ještě pořád si nejsu jistý, jestli to dělat tak plně automaticky přes šablonu {{Š|Pagebanner}}. Zatím to funguje dobře, jen možná parametr pro zoom mapy by mohl být zadaný ručně a v tom případě by bylo lepší mít samostatnou šablonu. Ale jestli vůbec má cenu mít na každé stránce vloženou šablonu <nowiki>{{Geo}}</nowiki> (výchozí zoom) a jen výjimečně něco jako <nowiki>{{Geo|zoom=10}}</nowiki>. Ale nevyužité šablony jako např. {{Š|PoiMap2}} už asi můžu odstranit. Budu rád, když si najdeš trochu času a ještě se zkusíš podívat, co dál by šlo vylepšit, protože v tomto se orientuješ velice dobře :) [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 14. 10. 2025, 10:53 (CEST) :::Výborně, nevyužité šablony jako {{šablona|PoiMap2}} a {{šablona|GeoData}} už jsou zbytečné. Jen bude potřeba upravit ještě {{šablona|Geo}}, aby už PoiMap2 nepoužívala. ::: Se zoomem asi nic moc dělat nepůjde – ruční zadávání by sice asi šlo přímo do {{šablona|Pagebanner}} (který by si to pak převzal do Geo části), ale to mi přijde zbytečně zatěžující. Možná by šlo zkusit vymyslet způsob, jak by se zoom určoval automaticky podle typu místa. Až budu mít víc času, podívám se na to podrobněji, teď mě ale čeká docela dost zápočtových testů, tak nevím úplně kdy přibližně to bude. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 14. 10. 2025, 11:17 (CEST) ::::PoiMap2 jsem odstranil. Ta nepůjde využít asi nikdy. GeoData jsem ještě nechal. Na tu jsem už zapomněl. Vypadá ještě do budoucna užitečně, i když zatím moc využitá není. Ten automatický zoom podle typu z Wikidat mně taky napadl, ale to bude až taková třešnička. Zatím jsem narazil na větší problém. V náhledu všechno funguje, ale při normálním zobrazení se ten indikátor se souřadnicemi v některých článcích vůbec neukáže. A jestli se ukáže, tak vypadá jinak, než v tom náhledu (bez textových souřadnic). Myslel jsem, že ten chybějící indikátor bude chtít čas na vyprázdnění cache, ale pořád to nejde. Takové věci se hledají blbě, když je chování v náhledu jiné :( [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 15. 10. 2025, 13:21 (CEST) == Chybějící města na mapě == Ahoj, ptám se tě jako specialisty na mapovou šablonu. :) Nevíš, proč se v článku [[Jihočeský kraj]] neukazují na mapě města, ale ostatní místa se ukazují? Je to neznámým typem objektu? Když u toho bodu natvrdo nastavím typ, tak se ukáže, ale nevidím důvod, proč by to nemělo ukazovat města. Navíc v článku [[Itálie]] se města normálně ukazují. Možná je problém s tím, že česká města jsou ve Wikidatech založena jako instance "obec v Česku" nebo "město v Česku", ale už ne obyčejné "město". Takže možná je to fakt neznámý objekt a takové objekty to neukazuje. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 25. 11. 2025, 18:12 (CET) :Aha, tak už jsem to opravil sám. Po dřívější aktualizaci nebylo přeložené jedno slovo v [[Modul:Marker utilities/Groups]]. Někdy stačí napsat dotaz, abych dostal další nápad. :) Ale s těmi městy na mapě mám ještě nějaké větší plány, tak se to bude hodit. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 25. 11. 2025, 18:17 (CET) == Aktualizace mapových modulů == Ahoj, právě jsem provedl asi největší aktualizaci všech těch mapových modulů, šablon a stylů za poslední dobu. Kvůli kontrole s předchozími ručními úpravami to bylo pracnější, než jsem myslel, ale vypadá to, že se všechno podařilo. Mým hlavním důvodem byly chybějící snad všechny ikony, které s tím souvisely, protože WM změnilo velikosti rastrových obrázků generovaných z vektorových. Aktualizoval jsem ale zrovna už všechno, na co jsem narazil. Čekal jsem, že se to zase totálně rozsype, ale zatím to vypadá dobře. V první řadě bych chtěl, aby ses na to aspoň podíval tvýma očima, ať identifikujeme případné problémy. Až pak se případně podíváme na jejich řešení, příp. přeložení nových textů (přeložil jsem zatím jen část). Díky [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 20. 5. 2026, 15:24 (CEST) 00slnjzwsb8fv2w000ugs6vlisahlca 22114 22113 2026-05-21T09:02:35Z OndraMix 385 /* Aktualizace mapových modulů */ odpověď 22114 wikitext text/x-wiki == Šablony s mapami == Díky za založení těch mapových šablon. Zatím jsem udělal nějaké rychlé překlady z němčiny, ale mám v plánu spolupracovat ještě víc. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 4. 10. 2024, 22:30 (CEST) :Děkuju za pomoc s překlady a odchycení překlepů. Teď plánuju překládat nové moduly a založit dokumentaci k [[Šablona:Bod|šabloně Bod]]. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 5. 10. 2024, 22:40 (CEST) == Modul:Exchangerate == Už dřív založil [[Modul:Exchangerate]] z enwikivoyage. Až se mně ji podařilo přeložit a propojit úspěšně s šablonami, tak jsem narážel na nějaké problémy a sám jsem uvažoval, že přejdu na německou verzi. Teď jsi vytvořil [[Modul:Exchange rate]] z dewikivoyage. Ten jsem zkusil opět lokalizovat a napasovat na existující šablony. Teď se mně to zdá všechno funkční a čerpám i z výhod té německé verze. Předpokládám, že tu anglickou už můžeme úplně smazat. Oprávnění k tomu mám, ale chtěl bych to od někoho potvrdit. Ještě bych chtěl zmínit, že obě verze mají jeden zásadní problém. Přestože vypadají, že se kurzy automaticky aktualizují, tak ve skutečnosti byl kurz z února 2023, kdy byl naposled aktualizovaný robotem. Teď jsem to aktualizoval po roce a půl ručně. Mám v plánu to občas aktualizovat. Spíš se divím, že to tak dlouhou dobu nikomu nechybělo. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 5. 10. 2024, 23:59 (CEST) :Ten modul z enwikivoyage je na smazání. Používá se jen u [[Šablona:Kurz|šablony Kurz]], což mi přijde, že je duplicita [[Šablona:Měna|šablony Měna]]. Když už budeš mazat ten modul, tak bych tě chtěl poprosit abys smazal i článek [[Vorlage:VCard/styles.css]], který jsem založil omylem. :S těmi kurzy to je skutečně zarážející, že to nikomu tak dlouho nevadilo. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 6. 10. 2024, 00:21 (CEST) ::Tvoji žádost o smazání jsem vyřešil. ::Šablony [[:Šablona:Kurz]] a [[:Šablona:Měna]] jsou si opravdu hodně podobné. Vypadá to, že Měna je taková vyšší úroveň a má sloužit pro zapisování částek v cizích měnách např. někde v textu. Kurz obsahuje spíš různé pomocné informace. Kurz ale momentálně není nikde používaný a to ani v šabloně Měna. Přesto jsem udělal úpravy, aby byl závislý pouze na novém modulu [[Modul:Exchange rate]]. ::Omlouvám se, ale nahoře jsem to napsal blbě. Původní modul [[Modul:Exchangerate]] (včetně šablony Měna) jsem nezakládal já, ale [[:Uživatel:Polda18]]. Já jsem jen pak dělal nějaké úpravy, aby to celé lepší fungovalo. Proto bych před definitivním smazáním původního modulu počkal aspoň týden, aby měl případný čas se k tomu vyjádřit i on. Pak bych to smazal. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 6. 10. 2024, 12:06 (CEST) :::(Sorry in English) hello I'm Tmv from Japanese Wikivoyage. I will leave a note about the Exchange rate. It is a known issue that the Commons data has not been updated, as stated on the [[:de:Modul:Exchange_rate/Doku|German documentation page]]. However, at this moment we have no alternative. For this reason, some Wikivoyage communities including German and Japanese ones have chosen not to use the currency conversion feature. :::Sorry for the delay, but welcome to the Wikivoyage community! --[[Uživatel:Tmv|Tmv]] ([[Diskuse s uživatelem:Tmv|diskuse]]) 6. 10. 2024, 13:19 (CEST) :::Šablona {{tl|Kurz}} měla být používána v průvodcích týkající se země, ve které se platí danou měnou, na kterou se ten kurz vztahuje. Zakládal jsem různé technické šablony z envoy, kde se musím přiznat, že jsem se v tom sám moc nevyznal, jaký v tom měli guláš. Pokud se šablona smaže, včetně jejího modulu, tak mi to vadit zřejmě nebude. Jazyku Lua moc nerozumím, takže jsem je v podstatě jen překopíroval (s odkazem na originál samozřejmě) a doufal, že někdo technicky znalejší by to mohl přeložit a případně opravit. Těch rozbitých a polofunkčních šablon a modulů je více. [[Uživatel:Polda18|Polda18]] ([[Diskuse s uživatelem:Polda18|diskuse]]) 6. 10. 2024, 13:59 (CEST) :::Super, Modul:Exchangerate jsem smazal a jedna duplicita je pryč a máme jen [[Modul:Exchange rate]]. :::Co se týká [[:Šablona:Kurz]], tak tu zatím nechám. Zkusíme víc používat [[:Šablona:Měna]] a uvidíme, co nám bude chybět a jestli nám šablona Kurz nepomůže. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 6. 10. 2024, 15:03 (CEST) ::::Dobrá. Kdyby bylo potřeba něco upravit nebo dodělat, jsem k dispozici, určitě se můžeme na něčem domluvit. Nemám problém se případně doučit jazyk Lua, abych mohl navrhovat úpravy modulů nebo moduly nové. Pro testovací účely si mohu udělat testovací wiki na localhostu. [[Uživatel:Polda18|Polda18]] ([[Diskuse s uživatelem:Polda18|diskuse]]) 8. 10. 2024, 11:28 (CEST) == Modul:VCard/i18n - název == Vidím, že experimentuješ s názvy parametrů na svém pískovišti a něco tam nefunguje. Asi to bude tím, že jsem změnil český název parametru v Modul:VCard/i18n. Původně tam bylo "jméno" a změnil jsem to na "název". Přijde mně to vhodnější. Je spíš "název místa" než "jméno místa". I v několika dalších překladech jsem původní "name" přeložil radši jako "název". Omlouvám se, pokud jsi díky tomu ztratil čas hledáním chyby. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 6. 10. 2024, 23:18 (CEST) :Název je určitě vhodnější než jméno. Jak toho teď překládám hodně, tak si takovéto věci občas neuvědomím. Děkuju za upozornění. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 7. 10. 2024, 09:59 (CEST) == Šablona:GPX indicator == Ahoj, teď jsem zkoumal, proč pořád nefunguje [[:Šablona:GPX indicator]], která se automaticky vkládá přes [[:Šablona:Pagebanner]], ale to asi bude fungovat až tady s těmi šablonami, které se teď vytváří. Ono je to navázané přes externí tool, tak k tomu moc nejde dohledat. Tak ať víš ještě o související šabloně, která vlastně není nikde vidět, ale projeví se jako ikona GPX vpravo nahoře. Ještě procházím všechny šablony, které často ani nejsou kategorizované, takže jsou těžko dohledatelné, a dělám v nich trochu pořádek a objevuju spoustu nových ještě nepoužitých. Přemýšlím, jestli tyto nové, na kterých právě pracuješ, zařadit i do kategorie Geografických nebo ne. Sice teoreticky můžou být použité jen jako prosté seznamy bez souřadnic a map, ale v principu je bude lepší mít jednoduše mezi geografickými, protože to je jejich hlavní účel. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 9. 10. 2024, 16:21 (CEST) :Děkuju za upozornění na šablonu GPX indicator, po letmém zhlédnutí mě napadlo jestli tomu nevadí jazyk čeština. Kdyžtak na [[:de:MediaWiki:Gadget-Poi2gpx.js|německých wikicestách]] mají asi trochu jinak (nedíval jsem se na to nějak detailněji). Šablony bod i mapa bych určitě vložil do geografických šablon. Někdy o víkendu bych se podíval na tu šablonu jestli se to do té doby nepodaří vyřešit a dodělal překlady a dokumentace. Momentálně nemám moc volného času. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 9. 10. 2024, 16:54 (CEST) :Já jsem ji původně bral jako jednu z podmínek k fungování toho nového Pagebanneru, tak jsem to nezkoumal, když tam nebyla ani dokumentace. Ten jazyk jsem taky zkoušel a při změně jazyka to funguje, ale odněkud si musí vzít ta data. Není tam v podstatě nic než konkrétní URL. Podle mě to si to webserver stáhne ze zadaných wikicest, zpracuje a vrátí hotový soubor. Na tu německou verzi jsem se díval až teď a dělá to asi stejnou věc, ale technologicky úplně jinak. Na první pohled odhaduju, že soubor je vygenerovaný na straně klienta pomocí Javascriptu. Německý přístup se mně líbí víc, protože se to dá nějak přizpůsobit a není to závislé na dalších službách. Až to bude použité na reálných stránkách, tak se to může vyzkoušet. A taky jestli není lepší způsob než paušální vkládání než přes pagebanner. :Každopádně díky za super práci! Je dobré tu mít dalšího odborníka :) [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 9. 10. 2024, 17:12 (CEST) == Problémy Geo šablony == Ahoj, zkusil jsem řešit problémy, proč jsou stránky občas v této kategorii: [[:Kategorie:Stránky s nesprávnými značkami zeměpisných souřadnic]]. Může za to {{Šablona|Geo}}, ve které se uvnitř nějak špatně předávají souřadnice nebo ve špatných formátech apod. Věnoval jsem tomu už dost času a nemůžu přijít na problém. Spíš jsem hledal konkrétní problém a konkrétní opravu, ale možná jsou tam složitě použité některé šablony a moduly, nebo je potřeba je nahradit jinými. Myslím, že by tento problém mohl souviset i s jinými problémy, které se týkají souřadnic. Jestli budeš mít někdy čas, zkus se na to prosím taky podívat, jestli něco objevíš. Na testování je vhodný článek [[Zlín]], který neobsahuje další geografické šablony. Díky [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 31. 1. 2025, 13:48 (CET) :Podívám se na to. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 31. 1. 2025, 14:00 (CET) :To vypadá, že už [[:Modul:Coord]] předané souřadnice formátuje nějak jinak, než se očekává. Ale ty souřadnice se zanoří postupně do tolika modulů, že nevím, co všechno by ovlivnila jakákoliv změna. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 31. 1. 2025, 16:04 (CET) ::Myslím že jsem to nějak opravil, [[Šablona:Coord|šablona Coord]] měla odkazovat na [[Modul:Coord|modul Coord]], ale odkazovala na [[Modul:Coordinates|Coordinates]]. Tohle je jen konkrétní oprava, nerozumím teď tomu jak ty moduly formátují souřadnice. Jinak stále je u [[Šablona:Geo|šablony Geo]] peoblém že na mapě zobrazuje body z enwikivoy a na českou ji nelze přepnout, proto jsem pracoval na [[Šablona:GeoData|šabloně GeoData]], která má aktuálně ale stejnej problém. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 31. 1. 2025, 16:20 (CET) :::Mohli bychom se vrátit k těm geografickým šablonám. Poslední cíl byl teda to, že by se šablona {{Š|Geo}} nahradila šablonou {{Š|GeoData}}, aby fungovalo otvírání mapy v pravém horním roku? A pořád nevím, jestli je úspěšně přidané [[MediaWiki:Gadget-MapTools.js]], protože se to zatím nijak neprojevuje, ale má to asi pracovat s tou šablonou {{Š|GeoData}}, takže to spolu bude souviset. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 13. 3. 2025, 22:34 (CET) ::::Ahoj, ::::Můj poslední cíl bylo nahradit Geo šablonou GeoData, jelikož nevím jestli je možné, aby dobře fungovala (jak to je externí nástroj). GeoData mají aktuálně 2 problémy: nezobrazují body na mapě a neregistrují články, aby se zobrazily když vyberu ''zobrazit články v okolí'' na mapě. Snažil jsem se najít, kde je chyba ale nemůžu to najít. Momentálně mám víc jiné práce a nemám sílu hledat kde v kódu bude chyba. Určitě to nějak souvisí s tím Gadgetem, možná se snaží volat něco co není pro něj dostupné. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 14. 3. 2025, 19:02 (CET) :::::Tak nakonec mi to nedalo, našel jsem že podle [[:de:Wikivoyage:Gadget-MapTools.js|nápovědy na německých wikicestách]] gadget vyžaduje seznam článků na Wikicestách (externí) a ten pro České Wikicesty [https://wikivoyage.toolforge.org/w/data/cs-articles.js není] (zatímco německé ho [https://wikivoyage.toolforge.org/w/data/de-articles.js mají]) Je to v [[MediaWiki:Gadget-MapTools.js#L-149|řádku 149 gadgetu]] <code>(scriptUrl = mw.format( 'https://wikivoyage.toolforge.org/w/data/$1-articles.js', pageLang ),</code>), tady může vznikat nějaký problém. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 14. 3. 2025, 19:13 (CET) :::::Konečně jsem vyřešil problém s šablonou {{Šablona|Geo}}. Problém je v tom, že uvnitř tagu indicator se proměnné nepřekládají. Proto musí tento tag generován jinou šablonou. Pak to už funguje. Takže odkaz už funguje, ale samozřejmě to nevyřešilo všechny problémy. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 20. 3. 2025, 23:23 (CET) == Kategorizace == Ahoj, mám jen malou poznámku ke kategorizaci. Na Wikicestách jsou na rozdíl od Wikipedie mnohem důležitější kategorie, které upřesňují ''kde to je'' než ''co to je''. Takže jsou vhodné kategorie, které geograficky upřesňují polohu, i když ne nutně administrativní dělení na kraje (i když je to často nejpohodlnější), ale raději tradiční regiony, hory apod. Prostě když někdo někomu říká, že jede na dovolenou na Šumavu, na Slovácko, do Vysokých Tater, ... Pak možná nějaké výjimečné typy konkrétních turistických cílů, které někdo vyhledává: hrady, lázně, ... To je můj pohled na kategorie v budoucnu :) [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 15. 4. 2025, 12:21 (CEST) :Ahoj, :souhlasím s kategorizací na základě polohy, ale myslím že kategorizace na základě typu je taky důležitá. Kdyby třeba někdo hledal cíle kam jet, třeba že chce jet do hor/na hrad, tak kategorie na základě typu můžou být užitečné pro vyhledání možných cílů. Za mě by byly nejlepší kategorie typu: [(stát/kraj) (typ)], [turistické regiony]; př. Slovinská města, Julské Alpy, Triglavský národní park pro ten [[Bled]]. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 15. 4. 2025, 14:54 (CEST) == Šablona Bod v Českých Budějovicích == Ahoj, pokud bys měl čas a chuť, tak se můžeš podívat na chování {{Šablona|Bod}} v článku [[České Budějovice]]. Musel jsem tam udělat takový hack, aby se to správně zobrazovalo. Problémy jsou tam dva: * Po odrážkách jsou následující body odsazené i když by neměly být. * Bod bez souřadnic se nezalomí na nový řádek. Nebo co si myslíš o takovém použití? Resp. viděl jsem i použití šablony uprostřed textu odstavce, což překvapivě nějak fungovalo, ale oprava výše uvedených problémů by to chování mohla ovlivnit. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 14. 5. 2025, 20:31 (CEST) :Ahoj, :podívám se na to, až budu mít trochu víc času. Toho že se šablona někdy nezalomuje na další řádek jsem si už všimnul, to odrážení je pro mě novinka. :Podle mě je dobré používat bod i do souvislého textu, hlavně kvůli propojení s Wikipedií/Commons..., dodání souřadnic místa do mapy a určitého vizuálního zvýraznění místa. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 14. 5. 2025, 23:05 (CEST) :Myslím, že mám dobrý postřeh. Problém se zalomením mají dva body po sobě, u kterých není vyplněn žádný popis (možná ani nic víc za ikonami). Pěkný příklad je [[Znojmo]], konkrétně tato verze: https://cs.wikivoyage.org/w/index.php?title=Znojmo&oldid=19492, která má dokonce dvě dvojice takových případů. Přidání parametru popis do kteréhokoliv bodu vyřeší problém v dané dvojici. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 20. 5. 2025, 10:23 (CEST) == Bod a Wikicesty == Ahoj, v článku [[Šumava]] je často použita šablona {{Š|Bod}} pro jednotlivé vrcholy. Teď začalo vznikat hodně článků o těchto jednotlivých vrcholech. Šablona zobrazuje odkazy na Wikipedii, Commons, Wikidata, ..., ale vlastně vůbec neumožňuje prokliknutí na článek na Wikicestách, který by dokonce v principu měl být ten nejdůležitější. Překvapuje mně to o to víc, že podle mě ani originální německá verze toto nemá vyřešeno. Nebo je tam něco, co jsem přehlédl? [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 9. 10. 2025, 10:13 (CEST) :Ahoj, myslím že v kódu je někde ikonka pro Wikicesty zakomentovaná, jelikož dělala chyby. Podívám se na to a zkusím to nějak opravit/dodělat ji tam. Dostanu se na to nejspíš někdy o víkendu. -- [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 9. 10. 2025, 10:47 (CEST) ::Ok, díky. Když se na to ale dívám z uživatelského pohledu, tak bych očekával, že odkaz na samotném názvu by měl vést na Wikicesty. To uživatel očekává. Nevím, jestli náhodný uživatel pozná a pochopí tu správnou malou ikonku za názvem. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 9. 10. 2025, 12:58 (CEST) :::Podíval jsem se na to a teď by šablona měla zobrazovat odkaz na Wikicesty v názvu a odkaz na externí web je řešen pomocí ikonky. Momentálně je nastaveno, že jediný odkaz na externí web je přes ikonku, ale dá se upravit, aby se v případě, že neexistuje odkaz na Wikicesty, zobrazoval externí odkaz i v názvu (viz [[Modul:Marker utilities]], řádek 1476). [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 12. 10. 2025, 05:26 (CEST) ::::Tak to je super! Tak jsem si to představoval. Já jsem to teda ještě upravil tak, jak jsi sám psal. Takže je to takový hybrid mezi tím, co bylo dřív a co jsi udělal. Prostě pokud existuje na Wikicestách, tak je tam odkaz na Wikicesty, pokud ne, tak externí odkaz, nebo pokud není, tak obyčejný text. Sice je tam teď ten externí odkaz ještě i s ikonkou zeměkoule, ale myslím, že to nevadí a kvůli jednotnosti je to možná i dobře. ::::Jinak ještě nějaké technické věci: ::::* Lua používá bool hodnotu false jen s malým f, takže False byla jakoby nedefinovaná proměnná a nebylo to požadované chování. ::::* Pokud už neplánuješ nějaké další úpravy, tak bych v Modul:VCard ještě ten nový kód zjednodušil (aby byl i podobnější tomu původnímu). Zkoušel jsem to a na první pohled jsem tam neviděl problém. ::::* Ještě asi udělám aktualizace celého modulu podle nejnovější verzi na DE Wikivoyage. Snad to něco nenabourá. ::::Jsem fakt rád, že jsi to dokázal a že se aspoň občas něco zlepšuje i technicky. Díky! [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 13. 10. 2025, 12:47 (CEST) :::::Určite jen do toho, nějaké úpravy v nejbližší době neplánuji. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 13. 10. 2025, 15:24 (CEST) :::::Zjednodušení jsem udělal. A i celá aktualizace proběhla docela bez problémů. Novinkou jsou např. odkazy na mapy u šablony {{Š|Bod}}. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 14. 10. 2025, 10:34 (CEST) ::::::Výborně, s tou mapou to vypadá moc dobře. Jen jsem si všiml, že po aktualizaci zmizela ikonka Wikidat ([[Šablona:VCard/styles.css]]). Otázka je, jestli je vůbec vhodné ji tam mít – za mě je docela užitečná, protože se dá jedním kliknutím přejít na Wikidata a upravit tam, ale pro běžného čtenáře asi takový význam nemá. ::::::Další změna je, že pokud existuje článek na Wikicestách, už nejde do šablony {{šablona|Bod}} přidat web místa (viz [[Šablona:Bod/test]] → ODKAZ NA WIKICESTY → druhý odkaz na Pražský hrad nebo druhý Třístoličník). [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 14. 10. 2025, 11:04 (CEST) :::::::Já jsem věděl, že je dobré, když se na to podívá ještě někdo jiný :) Toho jsem si nevšiml a už jsem to vrátil. Byla to ruční úprava, která se aktualizací přepsala. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 14. 10. 2025, 17:06 (CEST) :::::::Tak to jsem už taky opravil. Bylo to záludné, protože právě ta tebou speciálně upravená část kódu byla přesunuta do jiného modulu a už jsem to neuhlídal. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 14. 10. 2025, 18:14 (CEST) == Šablona Geo - Zobrazit články v okolí == Podařilo se mně zase trochu vylepšit ty věci kolem šablony {{Š|Geo}}. Volám ji automaticky s parametry z Wikidat pomocí {{Š|Pagebanner}}, takže je automaticky ve všech článcích, kde je tato šablona a kde jsou definované souřadnice, tzn. fakt skoro všechny. Funguje pak i to tlačítko Zobrazit články v okolí, což je super, aby bylo vidět, které články jsou založené poblíž jiného článku. Ještě trvá problém s tím, že ikona vpravo nahoře otevře jinou mapu, kde ty články v okolí nejsou, ale na to se ještě jednou podívám. Je potřeba otevřít mapu, která je vložena pomocí šablony {{Š|Mapa}}. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 13. 10. 2025, 14:13 (CEST) :Skvělá práce, u toho {{šablona|Geo}} je problém s {{šablona|PoiMap2}}, že ten web nemá českou verzi, která by přebírala data z českých Wikicesty. Napadlo mě to obejít přes [[Modul:Mapframe|modul Mapframe]], ale momentálně na to nemám moc času. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 13. 10. 2025, 15:35 (CEST) ::Přesně to napadlo i mě. Nakonec jsem udělal samostatnou šablonu {{Š|Maplink}}, která je ale v podstatě to samé (i stejný modul). Zdá se to být funkční a asi to tak nechám. Chtěl jsem to ještě nějak vizuálně vylepšit, ale moc mně to nejde. Ještě pořád si nejsu jistý, jestli to dělat tak plně automaticky přes šablonu {{Š|Pagebanner}}. Zatím to funguje dobře, jen možná parametr pro zoom mapy by mohl být zadaný ručně a v tom případě by bylo lepší mít samostatnou šablonu. Ale jestli vůbec má cenu mít na každé stránce vloženou šablonu <nowiki>{{Geo}}</nowiki> (výchozí zoom) a jen výjimečně něco jako <nowiki>{{Geo|zoom=10}}</nowiki>. Ale nevyužité šablony jako např. {{Š|PoiMap2}} už asi můžu odstranit. Budu rád, když si najdeš trochu času a ještě se zkusíš podívat, co dál by šlo vylepšit, protože v tomto se orientuješ velice dobře :) [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 14. 10. 2025, 10:53 (CEST) :::Výborně, nevyužité šablony jako {{šablona|PoiMap2}} a {{šablona|GeoData}} už jsou zbytečné. Jen bude potřeba upravit ještě {{šablona|Geo}}, aby už PoiMap2 nepoužívala. ::: Se zoomem asi nic moc dělat nepůjde – ruční zadávání by sice asi šlo přímo do {{šablona|Pagebanner}} (který by si to pak převzal do Geo části), ale to mi přijde zbytečně zatěžující. Možná by šlo zkusit vymyslet způsob, jak by se zoom určoval automaticky podle typu místa. Až budu mít víc času, podívám se na to podrobněji, teď mě ale čeká docela dost zápočtových testů, tak nevím úplně kdy přibližně to bude. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 14. 10. 2025, 11:17 (CEST) ::::PoiMap2 jsem odstranil. Ta nepůjde využít asi nikdy. GeoData jsem ještě nechal. Na tu jsem už zapomněl. Vypadá ještě do budoucna užitečně, i když zatím moc využitá není. Ten automatický zoom podle typu z Wikidat mně taky napadl, ale to bude až taková třešnička. Zatím jsem narazil na větší problém. V náhledu všechno funguje, ale při normálním zobrazení se ten indikátor se souřadnicemi v některých článcích vůbec neukáže. A jestli se ukáže, tak vypadá jinak, než v tom náhledu (bez textových souřadnic). Myslel jsem, že ten chybějící indikátor bude chtít čas na vyprázdnění cache, ale pořád to nejde. Takové věci se hledají blbě, když je chování v náhledu jiné :( [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 15. 10. 2025, 13:21 (CEST) == Chybějící města na mapě == Ahoj, ptám se tě jako specialisty na mapovou šablonu. :) Nevíš, proč se v článku [[Jihočeský kraj]] neukazují na mapě města, ale ostatní místa se ukazují? Je to neznámým typem objektu? Když u toho bodu natvrdo nastavím typ, tak se ukáže, ale nevidím důvod, proč by to nemělo ukazovat města. Navíc v článku [[Itálie]] se města normálně ukazují. Možná je problém s tím, že česká města jsou ve Wikidatech založena jako instance "obec v Česku" nebo "město v Česku", ale už ne obyčejné "město". Takže možná je to fakt neznámý objekt a takové objekty to neukazuje. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 25. 11. 2025, 18:12 (CET) :Aha, tak už jsem to opravil sám. Po dřívější aktualizaci nebylo přeložené jedno slovo v [[Modul:Marker utilities/Groups]]. Někdy stačí napsat dotaz, abych dostal další nápad. :) Ale s těmi městy na mapě mám ještě nějaké větší plány, tak se to bude hodit. [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 25. 11. 2025, 18:17 (CET) == Aktualizace mapových modulů == Ahoj, právě jsem provedl asi největší aktualizaci všech těch mapových modulů, šablon a stylů za poslední dobu. Kvůli kontrole s předchozími ručními úpravami to bylo pracnější, než jsem myslel, ale vypadá to, že se všechno podařilo. Mým hlavním důvodem byly chybějící snad všechny ikony, které s tím souvisely, protože WM změnilo velikosti rastrových obrázků generovaných z vektorových. Aktualizoval jsem ale zrovna už všechno, na co jsem narazil. Čekal jsem, že se to zase totálně rozsype, ale zatím to vypadá dobře. V první řadě bych chtěl, aby ses na to aspoň podíval tvýma očima, ať identifikujeme případné problémy. Až pak se případně podíváme na jejich řešení, příp. přeložení nových textů (přeložil jsem zatím jen část). Díky [[Uživatel:LiMr|LiMr]] ([[Diskuse s uživatelem:LiMr|diskuse]]) 20. 5. 2026, 15:24 (CEST) :Ahoj, :podívám se na to, dej mi pár dní, popř. dopopřekládám co bude třeba. Zběžným pohledem to vypadá dobře. [[Uživatel:OndraMix|OndraMix]] ([[Diskuse s uživatelem:OndraMix|diskuse]]) 21. 5. 2026, 11:02 (CEST) g7qgud4j3wzxillk14re2rfhu53mdqe Modul:Hours/i18n 828 1333 22102 17714 2026-05-20T12:07:25Z LiMr 96 aktualizace na novější verzi 22102 Scribunto text/plain -- kopie z německých wikicest (https://de.wikivoyage.org/w/index.php?title=Modul:Hours/i18n&oldid=1766826) -- copy from dewikivoyage (https://de.wikivoyage.org/w/index.php?title=Modul:Hours/i18n&oldid=1766826) -- This module contains wiki-language specific strings to translate. return { -- administration moduleInterface = { suite = "Hours", sub = "Hours/i18n", serial = "2026-04-07", item = 99744685 }, -- invoke call parameters params = { fallback = "", format = "", id = "", show = "" }, -- invoke-call show options show = { demo = "", msg = "", nomsg = "" }, -- Wikidata property identifiers wd = { retrieved = "P813", validInPeriod = "P1264", opened = "P3025", closed = "P3026", dayOpenFrom = "P3027", dayOpenTo = "P3028", natureOfStatement = "P5102", stateOfUse = "P5817", hourOpenFrom = "P8626", hourOpenTo = "P8627", appliesToJurisdiction = "P1001", appliesToPart = "P518", appliesToPeople = "P6001", occupation = "P106", of = "P642", use = "P366", all = { "P3026", "P3027", "P3028", "P8626", "P8627", "P1264", "P5102", "P5817", "P366", "P518", "P642", "P1001", "P6001", "P106" }, comments = { "P1264", "P5102", "P5817", "P366", "P518", "P642", "P1001", "P6001", "P106" }, commentsForClosed = { "P5102", "P5817", "P366", "P518", "P642", "P1001", "P6001", "P106" } }, -- abbreviations for month names months = { leden = "led", ["únor"] = "úno", ["březen"] = "bře", duben = "dub", ["květen"] = "kvě", ["červen"] = "čvn", ["červenec"] = "čvc", srpen = "srp", ["září"] = "zář", ["říjen"] = "říj", listopad = "lis", prosinec = "pro" }, weekdays = { Po = 1, ["Út"] = 2, St = 3, ["Čt"] = 4, ["Pá"] = 5, So = 6, Ne = 7 }, -- several strings texts = { closed = "uzavřeno: %s", format = "otevřeno: %s", -- punctuation parentheses = "(%s)", space = " ", -- for instance between days and times comma = ", ", -- several dates semicolon = "; ", -- several statesments from = "od %s", fromTo = "%s–%s", to = "do %s", -- formatting of a single time timePattern = "^(%d%d?)[.:](%d%d?)%s*Uhr$", -- for German wiki formatTime = "%s:%s", -- or "%s:%s Uhr" etc. formatDate = "j. M Y", formatAM = "%s:%s AM", formatPM = "%s:%s PM", -- formatting of a time range hourReplAll = true, -- (formally) replace all occurrences hourPattern = "", -- empty if no replacement is requested hourRepl = "", -- hourReplAll = false, -- replace only first occurrence -- hourPattern = "(%d)%s+[aApP][mM]", -- empty if no replacement is requested -- hourRepl = "%1", }, options = { addCategories = false, clusterClosed = true, -- cluster all closing dates at the end hour12 = false, -- 12 or 24 hours mode leadingZero = false, -- add or remove zero for hours removeZeros = false -- remove zeros :00 for full hours }, -- Category names categories = { fallbackLabel = "[[Kategorie:Údržba:Otevírací doba v angličtině]] <span class=\"voy-listing-check-recommended\" style=\"display:none;\">Otevírací doba v angličtině</span>", hoursFromWikidata = "[[Kategorie:Monitoring:Data z Wikidat]]", invalidId = "[[Kategorie:Údržba:Chyba v ID Wikidat]] <span class=\"error\">Chyba v ID Wikidat</span>", isClosed = "[[Kategorie:Údržba:Zařízení je uzavřeno]] <span class=\"voy-listing-check-recommended\" style=\"display:none;\">Zařízení je uzavřeno</span>", hoursLabelFromWikidata = "[[Kategorie:Monitoring:Data z Wikidat]] <span class=\"voy-listing-check-recommended\" style=\"display:none;\">Štítek otevírací doby z Wikidat</span>", properties = "[[Kategorie:Monitoring:Data z Wikidat]]", unknownError = "[[Kategorie:Údržba:Chyba v otevírací době]] <span class=\"voy-listing-check-recommended\" style=\"display:none;\">Chyba v otevírací době</span>", unknownParams = "[[Kategorie:Údržba:Neznámý parametr]] <span class=\"error\">Neznámý parametr: %s</span>", unknownShowOptions = "[[Kategorie:Údržba:Neznámá volba parametru show]] <span class=\"error\"Neznámá volba parametru show: %s</span>", withoutTime = "[[Kategorie:Údržba:Otevírací doba bez hodin]] <span class=\"voy-listing-check-recommended\" style=\"display:none;\">Otevírací doba bez hodin</span>", }, -- time to id conversion times = { daily = "Q26214163", Dec31 = "Q2912", is24_7 = "Q1571749", Jan1 = "Q2150" }, -- several abbreviations abbr = { { f = "[Pp]onděl[í|ky]", a = "Po" }, { f = "[Úú]ter[ý|ky]", a = "Út" }, { f = "[Ss]třed[a|y]", a = "St" }, { f = "[Čč]tvrt[ek|ky]", a = "Čt" }, { f = "[Pp]át[ek|ky]", a = "Pá" }, { f = "[Ss]obot[a|y]", a = "So" }, { f = "[Ss]obot[a|y] večer", a = "So" }, { f = "[Nn]eděle", a = "Ne" }, { f = "[Pp]rvní[ho]?", a = "1." }, { f = "[Dd]ruh[ý|á|é|ého]", a = "2." }, { f = "[Tt]řetí[ho]?", a = "3." }, { f = "[Čč]tvrt[ý|á|é|ého]", a = "4." }, { f = "[Pp]át[ý|á|é|ého]", a = "5." } }, -- selections of date labels to prevent fetching from Wikidata dateIds = { -- Table contains common values only and is used for reduction of -- computing time. Others will be taken from Wikidata labels. -- days Q105 = "Po", Q127 = "Út", Q128 = "St", Q129 = "Čt", Q130 = "Pá", Q131 = "So", Q132 = "Ne", Q211391 = "víkend", -- use Q99528581 instead of Q211391 because it is culturally dependent Q26214163 = "denně", -- do not remove this item because it is used in Lua script Q100274304 = "Po–Pá", Q116445783 = "Po–Út, Čt", Q118773943 = "Po–Út, Čt–Pá", Q104786164 = "Po-St", Q104057082 = "Po–Čt", Q97120402 = "Po–Pá", Q21282379 = "Po–So", Q101072294 = "Út–St", Q100320771 = "Út–Čt", Q100157387 = "Út–Pá", Q100148056 = "Út–So", Q99731947 = "Út–Ne", Q100427721 = "St–Čt", Q99714084 = "St–Pá", Q100148065 = "St–Pá", Q118773278 = "St, Pá", Q31689308 = "St–So", Q116328326 = "St, So", Q65681627 = "St–Ne", Q100332183 = "St–Ne", Q99731117 = "St–Po", Q106714964 = "Čt–Út", Q106538987 = "Čt–Pá", Q106541052 = "Čt–So", Q100274433 = "Čt–Ne", Q100427930 = "Pá–So", Q100451849 = "Pá–Ne", Q111977440 = "Pá–St", Q102268431 = "So–St", Q101766385 = "So–Čt", Q99528581 = "So–Ne", Q106538981 = "Ne–Po", Q111127796 = "Ne–St", Q100587968 = "Ne–Čt", Q112703547 = "Ne–Pá", Q1571749 = "24/7", -- do not remove this item because it is used in Lua script Q819073 = "pracovní den", Q1445650 = "svátek", Q1197685 = "svátek", Q2174956 = "den pracovního klidu", Q12779928 = "pracovní den", Q116213 = "dovolená", -- Zero-width spaces are used to keep the week-day terms and to -- prevent abbreviation Q14915111 = "52 dní před Velikonocemi", Q15834118 = "Weiberfastnacht", Q2245828 = "Nelkensams​tag", Q1241858 = "Estomihi", Q2085192 = "Estomihi", Q153134 = "Rosenmon​tag", Q4845365 = "masopustní​úterý", Q123542 = "Popeleční​středa", Q153308 = "3.​neděle​postní", Q2033651 = "5.​neděle​postní", Q42236 = "Květná​neděle", Q106333 = "Zelený​čtvrtek", Q40317 = "Velký​pátek", Q186206 = "Bílá​sobota", Q21196 = "Velikonoce", Q1512337 = "Velikonoční​neděle", Q209663 = "Velikonoční​pondělí", Q14795170 = "Velikonoční​pondělí", Q14916781 = "Velikonoční​úterý", Q51638 = "Svátek​Nanebevstoupení​Páně", Q39864 = "Letnice", Q2512993 = "Svatodušní​pondělí", Q14795386 = "51​dní​po​Velikonocích", Q152395 = "Slavnost​Těla​a​Krve​Páně", Q2304773 = "harvest​festival", Q2913791 = "Díkůvzdání", Q59833 = "Dušičky", Q19809 = "Vánoce", Q10901070 = "Svátek práce", Q10274 = "Vidžajadašamí", Q464458 = "Íd al-fitr", Q10259 = "Hólí", Q131772 = "Chinesisches Neujahrsfest", Q718778 = "Qingming-Fest", Q1145566 = "Chinesischer Nationalfeiertag", Q1622041 = "hlavní sezóna", Q99932986 = "mimosezóna", Q1777301 = "standardní čas", Q36669 = "letní čas", Q107376657 = "leden až březen", Q107376740 = "březen až říjen", Q121914265 = "březen až listopad", Q100157218 = "duben až říjen", Q107376636 = "duben až prosinec", Q107359921 = "květen až říjen", Q107376754 = "listopad až leden", Q100157227 = "listopad až březen", Q1312 = "jaro", Q1313 = "léto", Q1314 = "podzim", Q1311 = "zima", Q100320775 = "první víkend v měsíci", Q23034736 = "první pondělí v měsíci", Q51119351 = "druhé pondělí v měsíci", Q51119371 = "třetí pondělí v měsíci", Q51119385 = "čtvrté pondělí v měsíci", Q51119411 = "páté pondělí v měsíci", Q51120546 = "poslední pondělí v měsíci", Q51119341 = "první čtvrtek v měsíci", Q51119361 = "druhý čtvrtek v měsíci", Q51119378 = "třetí čtvrtek v měsíci", Q51119395 = "čtvrtý čtvrtek v měsíci", Q51119421 = "pátý čtvrtek v měsíci", Q51120559 = "poslední čtvrtek v měsíci", Q51119344 = "první pátek v měsíci", Q51119363 = "druhý pátek v měsíci", Q51119381 = "třetí pátek v měsíci", Q51119398 = "čtvrtý pátek v měsíci", Q51119425 = "pátý pátek v měsíci", Q51120563 = "poslední pátek v měsíci", Q51119345 = "první sobota v měsíci", Q51119367 = "druhá sobota v měsíci", Q51119382 = "třetí sobota v měsíci", Q51119402 = "čtvrtá sobota v měsíci", Q51119427 = "pátá sobota v měsíci", Q51120565 = "poslední sobota v měsíci", Q51119350 = "první neděle v měsíci", Q51119369 = "druhá neděle v měsíci", Q51119383 = "třetí neděle v měsíci", Q51119404 = "čtvrtá neděle v měsíci", Q51119429 = "pátá neděle v měsíci", Q51120567 = "poslední neděle v měsíci", Q108 = "leden", Q2150 = "1. leden", -- do not remove this item because it is used in Lua script Q196627 = "1. leden", Q2151 = "2. leden", Q2156 = "3. leden", Q2221 = "6. leden", Q1139536 = "26. leden", -- India Republic Day Q2289 = "31. leden", Q109 = "únor", Q2312 = "1. únor", Q2332 = "14. únor", Q2334 = "15. únor", Q2362 = "28. únor", Q2364 = "29. únor", Q110 = "březen", Q2393 = "1. březen", Q2404 = "14. březen", Q2403 = "15. březen", Q2457 = "27. březen", Q2458 = "28. březen", Q2461 = "31. březen", Q118 = "duben", Q2510 = "1. duben", Q2505 = "7. duben", Q2504 = "9. duben", Q2500 = "14. duben", Q2497 = "15. duben", Q2536 = "30. duben", Q119 = "květen", Q2544 = "1. květen", Q47499 = "1. květen", Q2574 = "16. květen", Q2591 = "31. květen", Q120 = "červen", Q2625 = "1. červen", Q2657 = "30. červen", Q121 = "červenec", Q2700 = "1. červenec", Q2715 = "31. červenec", Q122 = "srpen", Q2788 = "1. srpen", Q2774 = "15. srpen", Q162691 = "15. srpen", -- Assumption of Mary Q56106 = "15. srpen", -- Independence Day, India Q2830 = "31. srpen", Q123 = "září", Q2859 = "1. září", Q2846 = "15. září", Q2881 = "30. září", Q124 = "říjen", Q2913 = "1. říjen", Q2932 = "2. říjen", Q2931 = "3. říjen", Q157582 = "3. říjen", -- German Unity Day Q2919 = "15. říjen", Q2963 = "16. říjen", Q2949 = "31. říjen", Q153093 = "31. říjen", -- Reformation Day Q125 = "listopad", Q2997 = "1. listopad", Q2982 = "15. listopad", Q3029 = "16. listopad", Q3015 = "30. listopad", Q126 = "prosinec", Q2297 = "1. prosinec", Q2451 = "19. prosinec", Q2705 = "24. prosinec", Q106010 = "24. prosinec", Q2745 = "25. prosinec", Q2703710 = "25. prosinec", -- Christmas Day Q2761 = "26. prosinec", Q15113728 = "26. prosinec", Q2800 = "27. prosinec", Q2832 = "28. prosinec", Q2862 = "29. prosinec", Q2901 = "30. prosinec", Q2912 = "31. prosinec", -- do not remove this item because it is used in Lua script Q11269 = "31. prosinec", -- points of time Q573 = "den", Q575 = "noc", Q7722 = "ráno", Q986787 = "dopoledne", Q283102 = "odpoledne", Q7725 = "večer", Q193294 = "východ slunce", Q166564 = "západ slunce", Q36402 = "0:00", Q55812411 = "0:00", Q55449532 = "0:30", Q41618001 = "1:00", Q55517345 = "1:00", Q55518450 = "1:30", Q41618006 = "2:00", Q55521280 = "2:00", Q55524996 = "2:30", Q41618076 = "3:00", Q55527754 = "3:00", Q55560170 = "3:30", Q41618081 = "4:00", Q55810628 = "4:00", Q55810646 = "4:15", Q55811293 = "4:30", Q55811308 = "4:45", Q41618165 = "5:00", Q55810695 = "5:00", Q55810711 = "5:15", Q55811314 = "5:30", Q55811331 = "5:45", Q41618168 = "6:00", Q55810762 = "6:00", Q55810778 = "6:15", Q55810795 = "6:30", Q55811354 = "6:45", Q41618172 = "7:00", Q55811431 = "7:00", Q55810845 = "7:15", Q55810863 = "7:30", Q55811437 = "7:45", Q41618176 = "8:00", Q55811455 = "8:00", Q55810913 = "8:15", Q55810929 = "8:30", Q55810940 = "8:40", Q55812499 = "8:45", Q41618181 = "9:00", Q55811413 = "9:00", Q55811478 = "9:15", Q55810994 = "9:30", Q55811012 = "9:45", Q41618185 = "10:00", Q55811483 = "10:00", Q55811062 = "10:30", Q41618189 = "11:00", Q55811097 = "11:00", Q55811133 = "11:30", Q168182 = "12:00", Q55812521 = "12:00", Q55811197 = "12:30", Q47454201 = "12:30", Q41618345 = "13:00", Q55811230 = "13:00", Q55812556 = "13:15", Q55811580 = "13:30", Q55811277 = "13:45", Q41620570 = "14:00", Q55811610 = "14:00", Q55811657 = "14:15", Q55811674 = "14:30", Q55811761 = "14:45", Q41620574 = "15:00", Q55811778 = "15:00", Q55811726 = "15:15", Q55811745 = "15:30", Q55811798 = "15:45", Q41620578 = "16:00", Q55812393 = "16:00", Q55812563 = "16:15", Q55811847 = "16:30", Q55811864 = "16:45", Q41620582 = "17:00", Q55811883 = "17:00", Q55812585 = "17:15", Q55812595 = "17:25", Q55813015 = "17:30", Q55811932 = "17:45", Q41620584 = "18:00", Q55811949 = "18:00", Q55813021 = "18:15", Q55813038 = "18:30", Q55812002 = "18:45", Q41620587 = "19:00", Q55812019 = "19:00", Q55812659 = "19:30", Q41620591 = "20:00", Q55812694 = "20:00", Q55812122 = "20:30", Q41620593 = "21:00", Q55812716 = "21:00", Q55812732 = "21:15", Q55812192 = "21:30", Q55812210 = "21:45", Q41620595 = "22:00", Q55813122 = "22:00", Q55812769 = "22:30", Q44529925 = "23:00", Q55812301 = "23:00", Q55813170 = "23:30", Q55812370 = "24:00", -- for P1264 Q41662 = "Ramadán", -- for P5102 Q29509043 = "oficiální", Q29509080 = "neoficiální", Q132555 = "de jure", Q712144 = "de facto", Q28962310 = "zřídka", Q28962312 = "často", Q18603603 = "hypoteticky", Q30230067 = "možná", Q53737447 = "původně", Q18912752 = "sporné", Q28831311 = "nepotvrzené", Q24025284 = "občas se mění", Q4895105 = "prozatimní", Q18122778 = "pravděpodobně", Q32188232 = "údajně", Q1520777 = "jistě", Q5727902 = "cirka", Q56644435 = "zřejmě", -- for P5817 -- empty strings are not displayed Q29933838 = "mimo provoz", Q56651571 = "mimo provoz", Q111802839 = "mimo provoz", Q104664889 = "trvale uzavřeno", Q55570821 = "", -- "otevřeno pro veřejnost" Q55570340 = "zavřeno pro veřejnos", Q55654238 = "", -- "v provozu" Q811683 = "plánovaná stavba ", Q12377751 = "ve výstavbě", Q109551035 = "", -- "částečně funkční" Q63065035 = "", -- "opuštěno" Q11639308 = "vyřazeno z provozu", Q55653430 = "dočasně uzavřeno", Q63187954 = "v rekonstrukci", Q4989906 = "", -- "památka" Q2086116 = "", -- po použití Q110713763 = "zatím se nepoužívá" } } hewi4dh7wcuyf00mjvnmsdaubdc3hrh Modul:Hours 828 1334 22103 17231 2026-05-20T12:14:36Z LiMr 96 aktualizace na novější verzi 22103 Scribunto text/plain -- kopie z německých wikicest (https://de.wikivoyage.org/w/index.php?title=Modul:Hours&oldid=1775632) -- copy from dewikivoyage (https://de.wikivoyage.org/w/index.php?title=Modul:Hours&oldid=1775632) -- getting opening hours from Wikidata -- module variable and administration local hr = { moduleInterface = { suite = 'Hours', serial = '2026-05-17', item = 99600452 }, labelTable = nil, typeTables = nil } -- module import -- require( 'strict' ) local hi = require( 'Module:Hours/i18n' ) local wu = require( 'Module:Wikidata utilities' ) -- local variables local categIds = {} local showOptions = {} local function isSet( s ) return s and s ~= '' end -- insert a value into a table only if it is set local function tableInsert( tab, value ) if isSet( value ) then table.insert( tab, value ) end end -- value count for any variable local function getCount( tab ) return type( tab ) == 'table' and #tab or 0 end local function getLabelFromTables( id ) local label = hi.dateIds[ id ] if not label and hr.labelTable then label = hr.labelTable[ id ] end if not label and hr.typeTables and hr.typeTables.idTable then local item = hr.typeTables.typeTable[ hr.typeTables.idTable[ id ] ] if item then item = item.label or item.n or item local at = mw.ustring.find( item, ',' ) if at then item = mw.ustring.sub( item, 1, at - 1 ) end label = mw.text.trim( item ) end end return label end -- getting normalized time hh:dd local function getNormalizedTime( s ) local count s, count = mw.ustring.gsub( s, hi.texts.timePattern, '%1:%2' ) return ( count > 0 ) and s or nil end function hr.formatTime( s ) local t = getNormalizedTime( s ) if not t then return s end local formatStr = hi.texts.formatTime t = mw.text.split( t, ':', true ) if #t == 1 then t[ 2 ] = '00' end if hi.options.hour12 then local isAM = true local n = tonumber( t[ 1 ] ) if n > 12 then isAM = false t[ 1 ] = '' .. ( n - 12 ) end formatStr = isAM and hi.texts.formatAM or hi.texts.formatPM end s = mw.ustring.format( formatStr, mw.text.trim( t[ 1 ] ), mw.text.trim( t[ 2 ] ) ) if hi.options.leadingZero then s = s:gsub( '^(%d):', '0%1:' ) else s = s:gsub( '^0(%d):', '%1:' ) end if hi.options.removeZeros then s = s:gsub( '^(%d%d?):00', '%1' ) end return s end -- getting label for a qualifier id -- to save computing time firstly the id will fetched from Hours/i18n table -- if available, otherwise from Wikidata local function getLabelFromId( id, wikilang, fallbackLang ) if not isSet( id ) then return '' end -- from table local label = getLabelFromTables( id ) -- from Wikidata if not label and mw.wikibase.isValidEntityId( id ) then label = wu.getLabel( id, wikilang ) if not label and isSet( fallbackLang ) then label = wu.getLabel( id, fallbackLang ) if label then categIds.fallbackLabel = 1 end end if label then categIds.hoursLabelFromWikidata = 1 end end -- abbreviate labels if isSet( label ) then for i, abbr in ipairs( hi.abbr ) do label = mw.ustring.gsub( label, abbr.f, abbr.a ) end label = mw.ustring.gsub( label, '​', '' ) -- zero-width space end -- additional time formatting if isSet( label ) then if hi.months then for full, short in pairs( hi.months ) do label = mw.ustring.gsub( label, full, short ) end end label = hr.formatTime( label ) end return label or '' end local function abbreviateTimeStr( s, all, pattern, repl ) if not isSet( s ) or not isSet( pattern ) or not repl then return s or '' end if all then s = mw.ustring.gsub( s, pattern, repl ) else local matchPattern = mw.ustring.gsub( pattern, '%(%%d%)', '' ) local first, stop = mw.ustring.find( s, pattern ) if first then local second = mw.ustring.find( s, pattern, stop + 1 ) if second and mw.ustring.match( s, matchPattern ) == mw.ustring.match( s, matchPattern, stop + 1 ) then s = mw.ustring.gsub( s, pattern, repl, 1 ) end end end return s end -- getting time period string -- i: position in from and to arrays -- id: label for P3035 value local function getTimePeriod( from, to, i, id ) local result = '' if id and ( id == getLabelFromTables( hi.times.daily ) or id == getLabelFromTables( hi.times.is24_7 ) ) and from and to and from[ i ] == getLabelFromTables( hi.times.Jan1 ) and to[ i ] == getLabelFromTables( hi.times.Dec31 ) then return '' end if from and isSet( from[ i ] ) and to and isSet( to[ i ] ) then result = mw.ustring.format( hi.texts.fromTo, from[ i ], to[ i ] ) if isSet( hi.texts.hourPattern ) then result = abbreviateTimeStr( result, hi.texts.hourReplAll, hi.texts.hourPattern, hi.texts.hourRepl ) end elseif from and isSet( from[ i ] ) then result = mw.ustring.format( hi.texts.from, from[ i ] ) elseif to and isSet( to[ i ] ) then result = mw.ustring.format( hi.texts.to, to[ i ] ) end return result end -- collecting all maintenance categories function hr.getCategories( formatStr ) local result = wu.getCategories( formatStr ) for k, v in pairs( categIds ) do result = result .. ( hi.categories[ k ] or hi.categories.unknownError ) end if showOptions.demo then -- remove category links result = result:gsub( '%[%[[^%[]*%]%]', '' ) end return result end -- getting a string with listed days at which an establishment is closed local function getClosed( arr ) return ( arr and #arr > 0 ) and mw.ustring.format( hi.texts.closed or '%s', table.concat( arr, hi.texts.comma ) ) or '' end -- converting day range from Mo, Tu, We to Mo–We, and so on local function getRange( arr, minPos, maxPos ) if maxPos > 0 and minPos > 0 and maxPos > minPos then arr[ minPos ] = mw.ustring.format( hi.texts.fromTo, arr[ minPos ], arr[ maxPos ] ) for i = maxPos, minPos + 1, -1 do table.remove( arr, i ) end end end -- looking for day ranges like Mo, Tu, We and so on and converting them local function convertDayRange( arr ) local count = #arr local minPos = 0 local maxPos = 0 local value, valueMin while count > 0 do value = hi.weekdays[ arr[ count ] ] if not value then getRange( arr, minPos, maxPos ) maxPos = 0 elseif maxPos == 0 then maxPos = count valueMin = value elseif maxPos > 0 and value == valueMin - 1 then minPos = count valueMin = value else getRange( arr, minPos, maxPos ) maxPos = 0 end count = count - 1 end getRange( arr, minPos, maxPos ) end -- concating non-empty strings local function concatStrings( sep, str1, str2 ) local tab = {} tableInsert( tab, str1 ) tableInsert( tab, str2 ) return table.concat( tab, sep ) end -- add comment if not yet exists local function addComment( tab, value ) if not isSet( value ) then return elseif #tab == 0 then table.insert( tab, value ) else for i = 1, #tab, 1 do if tab[ i ] == value then break end if i == #tab then table.insert( tab, value ) end end end end -- main function for usage in Lua modules -- entity: entity id or entity table -- wikilang: content language of the wiki -- fallbackLang: optional additional language for fallback -- formatStr: optional format string for property categories -- show: table of show options (addCategories, msg, nomsg) or nil -- lastedit: dat of last edit. If false no date will be fetched -- labelTabel: additional table with Q-id label pairs function hr.getHoursFromWikidata( entity, wikilang, fallbackLang, formatStr, show, lastEdit, labelTable, typeTables ) -- collecting days at which an establishment is closed local closeDays = {} local closeDaysHelper = {} local withStateOfUse = false local function mergeDays( days ) if not days or #days == 0 then return end for i, day in ipairs( days ) do if not closeDaysHelper[ day ] then table.insert( closeDays, day ) closeDaysHelper[ day ] = '' end end end local function clearDays() closeDays = {} closeDaysHelper = {} end -- adding additional properties if an additional Q-id table is given hr.labelTable = labelTable hr.typeTables = typeTables -- preparing show options showOptions = show or {} showOptions.addCategories = hi.options.addCategories if showOptions.msg then showOptions.addCategories = true elseif showOptions.nomsg then showOptions.addCategories = false end -- format string for property categories if not isSet( formatStr ) then formatStr = hi.categories.properties end -- 1st step: getting statements for P3025: open days local statements = wu.getValuesWithQualifiers( entity, hi.wd.opened, nil, hi.wd.all, hi.wd.retrieved, nil, getLabelFromId, wikilang, fallbackLang ) lastEdit = wu.getLastedit( lastEdit, statements ) -- converting statements to human-readable strings local result = {} local comments, s local is24_7 = getLabelFromTables( hi.times.is24_7 ) for i, statement in ipairs( statements ) do -- opening times local times = {} local count = math.max( getCount( statement[ hi.wd.hourOpenFrom ] ), getCount( statement[ hi.wd.hourOpenTo ] ) ) if count > 0 then for j = 1, count, 1 do s = getTimePeriod( statement[ hi.wd.hourOpenFrom ], statement[ hi.wd.hourOpenTo ], j ) if isSet( s ) then table.insert( times, s ) elseif statement.value ~= is24_7 then categIds.withoutTime = 1 end end elseif statement.value ~= is24_7 then categIds.withoutTime = 1 end s = table.concat( times, hi.texts.comma ) -- comments comments = {} count = math.max( getCount( statement[ hi.wd.dayOpenFrom ] ), getCount( statement[ hi.wd.dayOpenTo ] ) ) for j = 1, count, 1 do addComment( comments, getTimePeriod( statement[ hi.wd.dayOpenFrom ], statement[ hi.wd.dayOpenTo ], j, statement.value ) ) end for j, key in ipairs( hi.wd.comments ) do if statement[ key ] then addComment( comments, table.concat( statement[ key ], hi.texts.comma ) ) end end -- concating times and comments times = {} tableInsert( times, s ) s = table.concat( comments, hi.texts.comma ) if isSet( s ) then table.insert( times, mw.ustring.format( hi.texts.parentheses, s ) ) end local item = {} tableInsert( item, table.concat( times, hi.texts.space ) ) -- close statements (P3026) as qualifiers for open days property (P3025) mergeDays( statement[ hi.wd.closed ] ) if not hi.options.clusterClosed and ( i == #statements or statements[ i ].value ~= statements[ i + 1 ].value ) then convertDayRange( closeDays ) tableInsert( item, getClosed( closeDays ) ) clearDays() end s = table.concat( item, hi.texts.comma ) -- copying each statement to result table if statement.sort2 == 1 then tableInsert( result, { value = { statement.value }, times = s } ) elseif s ~= '' then result[ #result ].times = concatStrings( hi.texts.comma, result[ #result ].times, s ) end end -- checking for duplicates for i = #result, 2, -1 do if result[ i ].times == result[ i - 1 ].times then for j, value in ipairs( result[ i ].value ) do table.insert( result[ i - 1 ].value, value ) end table.remove( result, i ) end end -- converting day range for i = 1, #result, 1 do local arr = result[ i ].value convertDayRange( arr ) result[ i ] = concatStrings( hi.texts.space, table.concat( arr, hi.texts.comma ), result[ i ].times ) end -- 2nd step: getting separated close statements (P3026) statements = wu.getValuesWithQualifiers( entity, hi.wd.closed, nil, hi.wd.commentsForClosed, hi.wd.retrieved, nil, getLabelFromId, wikilang, fallbackLang ) if #statements > 0 then lastEdit = wu.getLastedit( lastEdit, statements ) -- getting closed values local closed = {} for i, statement in ipairs( statements ) do local closedDate = {} table.insert( closedDate, statement.value ) -- getting comments comments = {} for j, key in ipairs( hi.wd.commentsForClosed ) do if statement[ key ] then addComment( comments, table.concat( statement[ key ], hi.texts.comma ) ) end end s = table.concat( comments, hi.texts.comma ) if isSet( s ) then table.insert( closedDate, mw.ustring.format( hi.texts.parentheses, s ) ) end table.insert( closed, table.concat( closedDate, hi.texts.space ) ) end mergeDays( closed ) end convertDayRange( closeDays ) tableInsert( result, getClosed( closeDays ) ) -- 3rd step: adding additional statements statements = wu.getValuesWithQualifiers( entity, hi.wd.stateOfUse, nil, {}, hi.wd.retrieved, nil, getLabelFromId, wikilang, fallbackLang ) if #statements > 0 then lastEdit = wu.getLastedit( lastEdit, statements ) for i, statement in ipairs( statements ) do if statement.value ~= '' then withStateOfUse = true table.insert( result, statement.value ) end end end -- merging all statements result = table.concat( result, hi.texts.semicolon ) -- adding maintenance categories if result ~= '' then categIds.hoursFromWikidata = 1 if withStateOfUse then categIds.isClosed = 1 end if showOptions.addCategories then result = result .. hr.getCategories( formatStr ) end end return result, lastEdit end -- invoke helper functions -- splitting show parameters local function splitAndCheck( s ) local arr = {} local err = {} if isSet( s ) then for i, v in ipairs( mw.text.split( s, ',', true ) ) do v = mw.text.trim( v ) if not hi.show[ v ] then table.insert( err, v ) else arr[ v ] = '' end end end return arr, err end -- check if pareameters are valid local function checkParameters( args ) local err = {} if not args and type( args ) ~= 'table' then return err end for k, v in pairs( args ) do if not hi.params[ k ] then table.insert( err, k ) end end return err end -- formating and concating error strings local function getErrorStr( arr, formatStr ) return #arr == 0 and '' or mw.ustring.format( formatStr, table.concat( arr, hi.texts.comma ) ) end -- main function for template #invoke calls -- id: Q id of an establishment -- format: output format like 'opened at %s' -- fallback: fallback language if labels are not available in content language function hr.getHours( frame ) local args = frame.args args.id = mw.text.trim( args.id or '' ) if not isSet( args.id ) or not mw.wikibase.isValidEntityId( args.id ) then return hi.categories.invalidId end if not isSet( args.format ) then args.format = hi.texts.format else local s, count = args.format:gsub( '%%s', '%%s' ) if count ~= 1 then args.format = hi.texts.format end end args.fallback = args.fallback or '' local wikilang = mw.getContentLanguage():getCode() local paramErr = checkParameters( args ) local show, showErr = splitAndCheck( args.show ) local result = hr.getHoursFromWikidata( args.id, wikilang, args.fallback, '', show, false, nil ) if result ~= '' then result = mw.ustring.format( args.format, result ) end return result .. getErrorStr( paramErr, hi.categories.unknownParams ) .. getErrorStr( showErr, hi.categories.unknownShowOptions ) end return hr 7iy3zw7sxfesklf9fjlgojnnrid06ol Modul:Marker utilities/i18n 828 1336 22106 22093 2026-05-20T12:27:23Z LiMr 96 formát data aktualizace 22106 Scribunto text/plain -- kopie z německých wikicest (https://de.wikivoyage.org/w/index.php?title=Modul:Marker_utilities/i18n&oldid=1768059) -- copy from dewikivoyage (https://de.wikivoyage.org/w/index.php?title=Modul:Marker_utilities/i18n&oldid=1768059) -- Separating code from internationalization return { -- module administration moduleInterface = { suite = 'Marker utilities', sub = 'i18n', serial = '2026-04-12', item = 65441686 }, dates = { yyyymmdd = { p = '^20[0-5]%d%-[01]?%d%-[0-3]?%d$', f = 'j. M Y' }, yyyy = { p = '^20[0-5]%d$', f = 'Y' }, yy = { p = '^[0-5]%d$', f = 'Y' }, mmdd = { p = '^[01]?%d%-[0-3]?%d$', f = 'j. M' }, dd = { p = '^[0-3]?%d%.?$', f = 'j.' }, mm = { p = '^[01]?%d%.?$', f = 'M' }, lastedit = { f = 'F Y' }, asOf = { f = 'n/Y' } }, fileExtensions = { 'tif', 'tiff', 'gif', 'png', 'jpg', 'jpeg', 'jpe', 'webp', 'xcf', 'ogg', 'ogv', 'svg', 'pdf', 'stl', 'djvu', 'webm', 'mpg', 'mpeg' }, months = { 'leden', 'únor', 'březen', 'duben', 'květen', 'červen', 'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec' }, monthAbbr = { 'led%.?', 'úno%.?', 'bře%.?', 'dub%.?', 'kvě%.?', 'čvn%.?', 'čvc%.?', 'srp%.?', 'zář%.?', 'říj%.?', 'lis%.?', 'pro%.?' }, -- Map related constants map = { coordURLformat = '//%s.wikivoyage.org/w/index.php?title=Special%%3AMapsources&params=%s_%s_%s&locname=%s', defaultDmsFormat = 'f1', -- see: Module:Coordinates/i18n defaultSiteType = 'type:landmark_globe:earth', defaultZoomLevel = 17, maxZoomLevel = 19, -- also to set in Module:GeoData, Module:Mapshape utilities/i18n }, -- Wikidata properties properties = { appliesToJurisdiction = 'P1001', appliesToPart = 'P518', appliesToPeople = 'P6001', capacity = 'P1083', centerCoordinates = 'P5140', commonsCategory = 'P373', coordinates = 'P625', endTime = 'P582', -- time headquartersLoc = 'P159', image = 'P18', instanceOf = 'P31', iso4217 = 'P498', languageOfName = 'P407', mainCategory = 'P910', maximumAge = 'P4135', minimumAge = 'P2899', nameInNativeLang = 'P1559', occupation = 'P106', of = 'P642', officialName = 'P1448', pointInTime = 'P585', propertyScope = 'P5314', -- for fees quantity = 'P1114', retrieved = 'P813', roomNumber = 'P8733', startTime = 'P580', -- time, for fees streetAddress = 'P6375', subclassOf = 'P279', unitSymbol = 'P5061', use = 'P366', validInPeriod = 'P1264' }, -- Groups of Wikidata properties propTable = { accessibility = { 'P2846' }, contactComments = { 'P366', 'P518', 'P642', 'P1001', 'P1559', 'P106' }, feeComments = { 'P5314', 'P518', 'P6001', 'P1264', 'P585', 'P2899', 'P4135', 'P642', 'P580' }, policyComments = { 'P518', 'P1001', 'P6001' }, quantity = { 'P1114', 'P1083' }, accessQuantity = { 'P1114', 'P1083', 'P2846' } }, -- Wikidata properties representing a qualifier qualifiers = { mobilePhone = 'Q17517', P8733 = 'Q180516', roomNumber = 'Q180516' }, -- Languages for fallbacks, except wiki language langs = { 'en', 'cs', 'de' }, -- array can be empty -- Display and performance options for vCard / Listing and Marker modules -- additional options in Module:VCard/i18n options = { excludeColorTypes = true, normalizeValues = { 'type', 'subtype', 'show', 'status', 'symbol' }, noStarParams = { 'nameExtra', 'nameLocal', 'alt', 'comment' }, noTypeMsgs = true, -- prevents display of maintenance( typeFromWD, typeIsGroup ) parameters = { 'commonscat', 'country', 'id', 'localLang', 'nameExtra', 'wikipedia' }, -- parameter is used showLocalData = true, -- names, addresses, directions showSisters = true, -- possible values true, false, 'atEnd' usePropertyCateg = true, -- create maintenance categories for Wikidata properties useTypeCateg = true, -- create maintenance categories for marker types markerMetadata = true, -- add metadata at marker templates -- text limit of content/description parameter contentLimit = 1000, groupsWithLimit = { buy = 1, drink = 1, eat = 1, sleep = 1 }, -- Wikidata related constants searchLimit = 4, -- count of levels for P31-P279 search -- useful but not necessary function calls WDmediaCheck = false, -- check file names retrieved from Wikidata mediaCheck = false, -- for better performance, otherwise expensive -- mw.title.new( 'Media:' .. image ) call is used secondaryCoords = false, -- adding listing coordinates to article database -- using #coordinates parser function skipPathCheck = false -- for URL check, see Module:UrlCheck }, -- strings texts = { asOf = '; stav %s', -- with semicolon separator from = 'od %s', fromTo = '%s–%s', to = 'do %s', fromTo2 = '%s až %s', -- General, i18n -- black x-like cross closeX = '[[File:Close x - black.png|15px|link=|class=noviewer|Unbekanntes Marker-Symbol]]', missingName = 'Chybí název', -- In case of CJK languages no spaces are used with punctuation -- Enumeration commas. voy-listing-comma is used for alt names only comma = '<span class="voy-listing-comma">, ​</span>', -- with zero-width space commaSeparator = ', ', period = '.', periodSeparator= '. ', -- Space following a punctuation mark space = ' ', nbSpace = '&nbsp;', parentheses = ' (%s)', emph = "''%s''", -- Formatting numbers: replacement patterns decimalPoint = ',', groupSeparator = '.', -- Anchor id anchor = 'vCard_%s', -- Marker CategoryNS = { '[Cc]ategory', '[Kk]ategorie' }, FileNS = { '[Ff]ile', '[Ss]oubor', '[Oo]brázek' }, latitude = 'Zeměpisná šířka', longitude = 'Zeměpisná délka', tooltip = 'Kliknutím na značku se otevře mapa.', -- vCard / Listing module checkin = 'Check-in: %s', checkout = 'Check-out: %s', closed = 'Uzavřeno: %s', closedPattern = '^[Uu]zavřeno:?%s*', editInSource = 'upravit ve zdrojovém článku', email = 'e-mail: %s', expirationPeriod = 'now - 3 years', fax = 'Fax: %s', hintName = 'Název v místním jazyce %s', hintLatin = 'Název v latinském přepisu', hintAddress = 'Adresa v místním jazyce %s', hintAddress2 = 'Adresa v %s', hintDirections = 'Pokyny v místním jazyce %s', hours = 'Otevřeno: %s', iata = '[[International Air Transport Association|IATA]]: %s', icao = '[[Mezinárodní organizace pro civilní letectví|ICAO]]: %s', lastedit = 'Aktualizace: %s', lasteditNone = 'není specifikováno', maybeOutdated = '(Informace mohou být zastaralé)[[Kategorie:Údržba:Bod:zastaralé informace]]', mobile = 'Mobil: %s', payment = 'Přijímané způsoby platby: %s', phone = '<abbr title="Telefon">Tel.</abbr>: %s', price = 'Cena: %s', subtype = 'Vlastnost: %s.', subtypes = 'Vlastnosti: %s.', subtypeAbbr = '<abbr title="%s">%s</abbr>', subtypeFile = '[[File:%s|x14px|link=|class=noviewer voy-listing-subtype-icon|%s]]', -- for subtype icons like Michelin stars subtypeSpan = '<span title="%s">%s</span>', subtypeWithCount = '%d %s', tollfree = '<abbr title="Telefon">Tel.</abbr> zdarma: %s' }, -- format strings for mu.addMaintenance formats = { category = '[[Kategorie:%s]]', error = ' <span class="error">%s</span>', hint = ' <span class="voy-listing-check-recommended" style="display: none;">%s</span>' }, -- maintenance maintenance = { -- general properties = '[[Kategorie:Monitoring:Data z Wikidat]]', --myslím že není třeba kategorizovat type = { category = 'Monitoring:Data z Wikidat' }, --myslím že není třeba kategorizovat group = { category = 'Monitoring:Data z Wikidat' }, --myslím že není třeba kategorizovat urlWithIP = { category = 'Údržba:Špatná URL', hint = 'URL obsahuje IP adresu' }, wrongUrl = { category = 'Údržba:Neplatná URL', err = 'neplatná URL' }, commonscatWD = { category = 'Monitoring:Data z Wikidat' }, --myslím že není třeba kategorizovat contentTooLong = { category = 'Údržba:Popis je příliš dlouhý', err = 'Popis je příliš dlouhý' }, -- currencyTooltip= { category = 'VCard: Währungstooltips eingesetzt' }, --myslím že není třeba kategorizovat dmsCoordinate = { category = 'Údržba:DMS-souřadnice', hint = 'DMS-souřadnice' }, duplicateAliases = { category = 'Údržba:Stránky s duplicitním voláním šablon', err = 'Duplicitní aliasy: %s' }, headquarters = { category = 'VCard: Koordinate der Hauptverwaltung' }, labelFromWD = { category = 'Monitoring:Data z Wikidat', hint = 'Štítek z Wikidat' }, --myslím že není třeba kategorizovat; když tam kategorie není tak to hází chybu -- linkIsRedirect = { category = 'VCard: Artikellink ist Weiterleitung' }, --myslím že není třeba kategorizovat linkToOtherWV = { category = 'Údržba:Odkaz na jiné wikicesty' }, malformedName = { category = 'Údržba:Špatný název', err = 'Špatný název' }, missingImg = { category = 'Údržba:Stránky s neexistujícím souborem', err = 'Neexistující soubor: %s' }, missingNameMsg = { category = 'Údržba:Šablona Bod beze jména', err = 'Chybí název' }, missingType = { category = 'Údržba:Šablona Bod bez typu', hint = 'Chybí typ' }, nameFromWD = { category = 'Monitoring:Data z Wikidat', hint = 'Název z Wikidat' }, --myslím že není třeba kategorizovat nameWithStar = { category = 'Údržba:Šablona Bod s hvězdičkou ve jméně', err = 'Název obsahuje hvězdičku' }, outdated = { category = 'Údržba:Akce ukončena', err = 'Akce ukončena' }, parameterUsed = { category = 'Údržba:Použitý parametr %s' }, --myslím že není třeba kategorizovat deleteShowCopy = { category = 'Údržba:Kopie smazána', hint = 'show=kopie smazána' }, -- showInlineUsed = { category = 'VCard: show=inline gesetzt' }, --myslím že není třeba kategorizovat -- showNoneUsed = { category = 'VCard: show=none gesetzt' }, -- showPoiUsed = { category = 'VCard: show=poi gesetzt' }, --myslím že není třeba kategorizovat typeFromWDchain= { category = 'Monitoring:Data z Wikidat', hint = 'Typ z Wikidat' }, -- typeIsGroup = { category = 'Údržba:Chybné hodnoty', hint = 'Typ je název skupiny' }, -- typeIsColor = { category = 'Údržba:Chybné hodnoty', hint = 'Typ je název barvy' }, -- typeIsColor is not used if excludeColorTypes = true unknownCountry = { category = 'Údržba:Články s neznámým kódem země', err = 'Neznámý kód země' }, unknownGroup = { category = 'Údržba:Šablona Bod s neznámou skupinou', err = 'Neznámá skupina' }, unknownLanguage= { category = 'Údržba:Šablona Bod s neznámým jazykem', hint = 'Neznámý místní jazyk' }, unknownParam = { category = 'Údržba:Články s neznámými parametry', err = 'Neznámý parametr: %s' }, unknownParams = { category = 'Údržba:Články s neznámými parametry', err = 'Neznámé parametry: %s' }, unknownPropertyLanguage= { category = 'Údržba:Šablona Bod s neznámým jazykem', hint = 'Neznámý jazyk pro vlastnost' }, unknownStatus = { category = 'Údržba:Šablona Bod s neznámým statusem', err = 'Neznámý status' }, unknownType = { category = 'Údržba:Chybné hodnoty', err = 'Neznámý typ: %s' }, -- unusedRedirect = { category = 'VCard: Unbenutzter Weiterleitungs-Sitelink' }, urlIsSocialMedia = { category = 'Údržba:Špatná URL', err = 'URL ze sociálních sítí' }, wikidata = { category = 'Monitoring:Data z Wikidat' }, wrongCoord = { category = 'Údržba:Šablona Bod s chybějícími souřadnicemi', err = 'Chybné souřadnice' }, wrongImgName = { category = 'Údržba:Chybný název souboru', err = 'Chybný název souboru' }, wrongQualifier = { category = 'Údržba:Nesprávný odkaz na Wikidata', err = 'Nesprávný odkaz na Wikidata' }, -- Marker module missingCoord = { category = 'Údržba:Šablona Bod s chybějícími souřadnicemi', err = 'Chybí souřadnice' }, numberUsed = { category = 'Údržba:Chybné hodnoty' }, unknownIcon = { category = 'Údržba:Chybné hodnoty' }, -- vCard / Listing module countryFromWD = { category = 'Monitoring:Data z Wikidat' }, missingCoordVc = { category = 'Údržba:Šablona Bod s chybějícími souřadnicemi' }, paymentUsed = { category = 'Monitoring:Zadána platební metoda' }, socialUrlUsed = { category = 'Údržba:URL sociálních sítí', hint = 'Použita URL sítě %s' }, unitFromWD = { category = 'Monitoring:Data z Wikidat' }, unknownLabel = { category = 'Údržba:Neznámý štítek nebo id' }, unknownMAKI = { category = 'Údržba:Neznámý symbol MAKI', hint = 'Neznámý symbol MAKI' }, unknownShow = { category = 'Údržba:Chybné hodnoty', err = 'Hodnota(y) pro show neznámá: %s' }, unknownSubtype = { category = 'Údržba:Chybné hodnoty', err = 'Hodnota(y) pro podtyp neznámý: %s' }, unknownUnit = { category = 'Údržba:Chybné hodnoty', hint = 'Neznámá entita' }, unknowWDfeatures = { category = 'Údržba:Šablona Bod s neznámými charakteristikami Wikidat', hint = 'Neznámé charakteristiky Wikidat' }, wdWithGoogleCid = { category = 'VCard: Parametr google-maps používaný společně s Wikidaty', hint = 'google-maps použito s Wikidaty' }, wikidataWithId = { category = 'VCard: Parametr id používaný společně s Wikidaty', hint = 'id použito s Wikidaty' }, wrongDate = { category = 'Údržba:Články s chybami v datech', hint = 'Nesprávné datum' }, wrongGoogleCid = { category = 'VCard: Nesprávné ID zákazníka Google map', err = 'Nesprávné ID zákazníka Google map' }, wrongId = { category = 'VCard: Nesprávné id', err = 'Nesprávné id' }, wrongSocialId = { category = 'Údrža:Nesprávné ID sociální sítě', err = 'Nesprávné ID %s' }, wrongSocialUrl = { category = 'Údržba:Neplatná URL', err = 'Chybná URL %s' } }, iconTitles = { commons = '%s na Wikimedia Commons', facebook = '%s na Facebooku', flickr = '%s na Flickru', instagram = '%s na Instagramu', internet = 'Web tohoto místa', maps = '%s na mapách a v plánovačích tras', rss = 'RSS webový zdroj této instituce', tiktok = '%s na TikToku', wikidata = '%s (%s) na Wikidatech', wikipedia = '%s na Wikipedii', wikivoyage = '%s na Wikicestách (Wikivoyage) v jiném jazyce', x = '%s na X', youtube = '%s na YouTube' }, -- social media services services = { { key = 'facebook', url = 'https://www.facebook.com/%s', pattern = { '^[-.%d%w][-_.%d%w]+$', '^[^%z\1-,/:-?\91-\94{-~]+/[1-9]%d+$' } }, { key = 'flickr', url = 'https://www.flickr.com/photos/%s', pattern = '^%d%d%d%d%d+@N%d%d$' }, { key = 'instagram', url = 'https://www.instagram.com/%s/', pattern = { '^[0-9a-z_][0-9a-z._]+[0-9a-z_]$', '^explore/locations/%d+$' } }, { key = 'tiktok', url = 'https://www.tiktok.com/@%s', pattern = '^[0-9A-Za-z_][0-9A-Za-z_.]+$' }, { key = 'x', url = 'https://x.com/%s', pattern = '^[0-9A-Za-z_]+$' }, { key = 'youtube', url = { 'https://www.youtube.com/channel/%s', 'https://www.youtube.com/%s' }, pattern = { '^UC[-_0-9A-Za-z]+[AQgw]$', '^@[-0-9A-Za-z_.][-0-9A-Za-z_.][-0-9A-Za-z_.]+$' } } }, --[[ status symbols g: successive symbol group number alias: status alias label: image tag title category = 1: add maintenance category --]] statuses = { ['top-hotel'] = { g = 1, label = 'Top-Hotel', category = 1 }, ['top-restaurant'] = { g = 1, label = 'Top-Restaurace', category = 1 }, ['top-sight'] = { g = 1, label = 'Top-Atrakce', category = 1 }, recommendation = { g = 1, label = 'Doporučení' }, none = { g = 2, alias = 'class-0', label = "Bez klasifikace" }, stub = { g = 2, alias = 'class-1', label = "Pahýl" }, outline = { g = 2, alias = 'class-2', label = "Návrh článku" }, usable = { g = 2, alias = 'class-3', label = "Užitečný článek" }, guide = { g = 2, alias = 'class-4', label = "Celý článek" }, star = { g = 2, alias = 'class-5', label = "Doporučený článek" } }, -- Marker name styles -- Colors in Template:VCard/styles.css nameStyles = { inherit = 'font-weight: inherit; font-style: inherit;', italic = 'font-weight: normal; font-style: italic;', kursiv = 'font-weight: normal; font-style: italic;', -- de: kursiv = italic normal = 'font-weight: normal; font-style: normal;', station = 'font-weight: normal; white-space: nowrap; padding-left: 2px; padding-right: 2px;' }, -- yes/no variants yesno = { y = 'y', yes = 'y', j = 'y', ja = 'y', a = 'y', ano = 'y', n = 'n', no = 'n', nein = 'n', ne = 'n' }, -- List of currencies without conversion tooltips noCurrencyConversion = { -- all = 1, -- no rate conversion tooltips are shown -- there is no confusion with (uppercase) ALL = "Q125999" EUR = 1 -- local currency }, -- Language-dependent sorting substitutes substitutes = { { l = 'ä', as = 'a' }, { l = 'ö', as = 'o' }, { l = 'ü', as = 'u' }, { l = 'ß', as = 'ss' } } } 5fz0w74j7zehv2sdervy438hefkl6bt MediaWiki:Gadget-Poi2gpx.js 8 1461 22112 18326 2026-05-20T13:04:42Z LiMr 96 aktualizace na novější verzi 22112 javascript text/javascript //<nowiki> /********************************************************************/ // Přeneseno z https://de.wikivoyage.org/wiki/MediaWiki:Gadget-Poi2gpx.js /********************************************************************* * poi2gpx v1.5, 2026-04-21 * Download of article’s points of interest and tracks to a GPX file * Original author: Roland Unger * Support of desktop and mobile views * Documentation: https://de.wikivoyage.org/wiki/Wikivoyage:Gadget-Poi2gpx.js * License: GPL-2.0+, CC-by-sa 3.0 *********************************************************************/ /* eslint-disable mediawiki/class-doc */ ( function ( $, mw ) { 'use strict'; // technical constants const version = '2026-04-21', minervaPageActionsSelector = '.page-actions-menu #page-actions-edit', imgSrc = '//upload.wikimedia.org/wikivoyage/de/thumb/5/5f/WV-poi2gpx-green.svg/60px-WV-poi2gpx-green.svg.png', imgSrcMinerva = '//upload.wikimedia.org/wikivoyage/de/thumb/6/63/WV-poi2gpx-black.svg/60px-WV-poi2gpx-black.svg.png', // image for download link allowedNamespaces = [ 0, // Main 2, // User 4 // Project ], commentClasses = [ 'voy-listing-hours', 'voy-listing-checkin', 'voy-listing-checkout', 'voy-listing-price', 'voy-listing-credit' ], containerClass = 'vcard', // contains wrapper markup of a single marker or listing contentClass = 'voy-listing-content', dataColor = 'data-color', dataName = 'data-name', dataPhone = 'data-phone', dataType = 'data-group', // other wikis: 'data-type' dataUrl = 'data-url', dataMw = 'data-mw', fallbackLang = 'en', kartographerClass = 'mw-kartographer-maplink', nameClass = 'voy-listing-name', noGpxClass = 'voy-listing-no-gpx'; // strings depending on page language // depending on group names defined in Module:Marker utilities/Groups const wikiStrings = { de: { track: 'Track' }, en: { track: 'track' }, es: { track: 'sendero' }, fr: { track: 'piste' }, it: { track: 'traccia' }, cs: { track: 'trasa' } }; // strings depending on user language const userStrings = { de: { gpxFileDescr: 'Kartenpositionen aus dem deutschen Wikivoyage-Artikel', gpxLabel: 'GPX', gpxTitle: 'Download der Kartenpositionen als GPX-Datei' }, en: { gpxFileDescr: 'Map positions from the German Wikivoyage article', gpxLabel: 'GPX', gpxTitle: 'Download of the map positions as a GPX file' }, es: { gpxFileDescr: 'Posiciones en el mapa del artículo de Wikivoyage en alemán', gpxLabel: 'GPX', gpxTitle: 'Descarga de las posiciones del mapa como archivo GPX' }, fr: { gpxFileDescr: 'Positions sur la carte de l’article de Wikivoyage allemand', gpxLabel: 'GPX', gpxTitle: 'Téléchargement des positions de la carte sous forme de fichier GPX' }, it: { gpxFileDescr: 'Posizioni sulla mappa dall’articolo tedesco di Wikivoyage', gpxLabel: 'GPX', gpxTitle: 'Download delle posizioni della mappa come file GPX' }, cs: { gpxFileDescr: 'Pozice na mapě z článku na českých Wikicestách', gpxLabel: 'GPX', gpxTitle: 'Stáhnout mapové body jako soubor GPX' } }; // internal use const pageLang = mw.config.get( 'wgPageContentLanguage' ), userLang = mw.config.get( 'wgUserLanguage' ), pageTitle = mw.config.get( 'wgTitle' ), isMinerva = mw.config.get( 'skin' ) === 'minerva'; // mobile view let gpxFile = null, // check for URL object trackdata = null, messages = {}; // copying translation strings to messages depending on chain languages const addMessages = ( strings, chain ) => { for ( let i = chain.length - 1; i >= 0; i-- ) { if ( strings.hasOwnProperty( chain[ i ] ) ) { $.extend( messages, strings[ chain[ i ] ] ); } } }; // copying translation strings to messages const setupMessages = () => { addMessages( wikiStrings, [ pageLang, fallbackLang ] ); const chain = ( userLang == pageLang ) ? [ pageLang, fallbackLang ] : [ userLang, pageLang, fallbackLang ]; addMessages( userStrings, chain ); }; // to use text in XML tags const htmlEncode = ( text ) => { return text.replace( /\&/g, '&amp;' ) .replace( /"/g, '&quot;' ) .replace( /</g, '&lt;' ) .replace( />/g, '&gt;' ); }; const removeTags = ( s ) => { return $( '<div>' + s + '</div>' ).text(); }; const getString = ( prop ) => { if ( !prop ) { return ''; } if ( typeof( prop ) == 'string' ) { return prop; } if ( prop[ pageLang ] ) { return prop[ pageLang ]; } else if ( prop.en ) { return prop.en; } for ( let i in prop ) { return prop[ i ]; } return ''; }; const makeFile = ( text ) => { // modern Browsers const data = new Blob( [ text ], { type: 'application/gpx+xml' } ); if ( !gpxFile ) { window.URL.revokeObjectURL( gpxFile ); } gpxFile = window.URL.createObjectURL( data ); return gpxFile; }; const getPhone = ( selector, $this ) => { const v = $( selector, $this ).first(); if ( v.length ) { let phone = v.attr( dataPhone ); if ( phone ) { return phone; } } return ''; }; // Getting GeoJSON data sets from external sources (OSM, Commons) const getGeoJSON = ( obj ) => { let promise, coordinates, geometry, i; const properties = obj.properties; // for all but not for 'page' promise = $.getJSON( obj.url ).then( function( geoJSON ) { switch ( obj.service ) { case 'page': // from Commons if ( geoJSON.jsondata && geoJSON.jsondata.data ) { $.extend( obj, geoJSON.jsondata.data ); } break; case 'geoline': // from OSM case 'geoshape': $.extend( obj, geoJSON ); if ( properties ) { for ( i = 0; i < obj.features.length; i++ ) { if ( $.isEmptyObject( obj.features[ i ].properties ) ) { obj.features[ i ].properties = properties; } else { obj.features[ i ].properties = $.extend( {}, properties, obj.features[ i ].properties ); } } } } }, function() { // failed, no tracks will be added } ); return promise; }; // getting Kartographer live data. It is used to extract information on // external data if these are members of the track group const getKartographerLiveData = () => { let i, obj, promiseArray = []; const liveData = mw.config.get( 'wgKartographerLiveData' ); if ( liveData ) { trackdata = liveData[ messages.track ]; if ( trackdata && !trackdata.length ) { trackdata = null; } if ( trackdata ) { for ( i = 0; i < trackdata.length; i++ ) { obj = trackdata[ i ]; if ( obj.type === 'ExternalData' && obj.url ) { promiseArray.push( getGeoJSON( obj ) ); } } } } // wait for getting all external data if ( typeof Promise !== 'undefined' ) { Promise.all( promiseArray ) .then( function() { createFile(); } ) .catch( function() { createFile(); } ); // create file also in case of failures } else { createFile(); } return; }; // format a single track for use in a gpx file const writeTrack = ( coordinates, tracks, type, properties ) => { if ( !coordinates || !coordinates.length ) { return tracks; } let j, k, s, coords; tracks += '\n <trk>\n'; if ( properties ) { s = htmlEncode( removeTags( getString( properties.title ) ) ); if ( s ) { tracks += ' <name>' + s + '</name>\n'; } s = htmlEncode( removeTags( getString( properties.desc ) ) ); if ( s ) { tracks += ' <desc>' + s + '</desc>\n'; } if ( properties.stroke ) { tracks += ' <extensions>\n' + ' <gpxx:WaypointExtension xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3">\n' + ' <gpxx:DisplayColor>' + properties.stroke + '</gpxx:DisplayColor>\n' + ' </gpxx:WaypointExtension>\n' + ' </extensions>\n'; } } for ( j = 0; j < coordinates.length; j++ ) { coords = coordinates[ j ]; if ( type === 'MultiPolygon' ) { coords = coordinates[ j ][ 0 ]; // only first polygon // tests not yet completed } if ( coords.length ) { tracks += ' <trkseg>\n'; for ( k = 0; k < coords.length; k++ ) { tracks += ' <trkpt lat="' + coords[ k ][ 1 ] + '" lon="' + coords[ k ][ 0 ] + '" />\n'; } tracks += ' </trkseg>\n'; } } return tracks + ' </trk>\n'; }; // callect all tracks which are members of the track group const writeTracks = () => { if ( !trackdata || !trackdata.length ) { return ''; } let i, coordinates, geoJSON, geometry, properties, tracks = ''; for ( i = 0; i < trackdata.length; i++ ) { if ( trackdata[ i ].features ) { geoJSON = trackdata[ i ].features[ 0 ]; geometry = geoJSON.type === 'Feature' ? geoJSON.geometry : geoJSON; coordinates = geometry ? geometry.coordinates : null; properties = geoJSON.properties; switch ( geometry.type ) { case 'LineString': tracks = writeTrack( [ coordinates ], tracks, 'MultiLineString', properties ); break; case 'MultiLineString': case 'Polygon': tracks = writeTrack( coordinates, tracks, 'MultiLineString', properties ); break; case 'MultiPolygon': tracks = writeTrack( coordinates, tracks, 'MultiPolygon', properties ); } } } return tracks; }; // get information from all markers (vCard and marker templates) exluding // external data and put them into xml of gpx files. Adding track data // at the end const getText = () => { // generate GPX output let markers = $( '.' + containerClass ).not( '.' + noGpxClass ); if ( !markers.length ) { return ''; } let aType, cmt, color, count, desc, gpxx, i, link, lat, lon, name, text = '', params, v, minlat = null, minlon = null, maxlat = null, maxlon = null; // for bounds markers.each( function() { const $this = $( this ); link = $( '.' + kartographerClass, $this ).first(); if ( link.length ) { lat = link.attr( 'data-lat' ); lon = link.attr( 'data-lon' ); if ( minlat === null || lat < minlat ) { minlat = lat; } if ( minlon === null || lon < minlon ) { minlon = lon; } if ( maxlat === null || lat > maxlat ) { maxlat = lat; } if ( maxlon === null || lon > maxlon ) { maxlon = lon; } color = $this.attr( dataColor ); aType = $this.attr( dataType ); // fallback legacy parser // dataMw is only available if Parsoid was used params = link.attr( dataMw ); if ( params ) { params = params.replace( /&quot;/g, '"' ); try { params = JSON.parse( params ); } catch ( e ) { // invalid JSON params = {}; } // params.attrs.group contains the value of the group // argument of the maplink tag, ie. the translated group // value if ( params.attrs && params.attrs.group ) { aType = params.attrs.group; } } count = link.html(); if ( count.indexOf( '<' ) >= 0 ) { count= ''; // no number but html tag } else { count = ' ' + ( '0' + count ).slice( -2 ); } name = $this.attr( dataName ); if ( !name ) { name = $( '.' + nameClass, $this ).first(); } name = htmlEncode( removeTags( name ) ); desc = $( '.' + contentClass, $this ).first(); desc.find( '.voy-listing-map, .voy-listing-coordinates' ).remove(); desc = ( desc.length ) ? htmlEncode( desc.text().replace( /​/g, '' ).replace( /\s+/g, ' ' ) ) : ''; // removal of whitespaces and zero-width spaces cmt = ''; for ( i = 0; i < commentClasses.length; i++ ) { v = $( '.' + commentClasses[ i ], $this ).first(); if ( v.length ) { if ( cmt ) { cmt += ' '; } cmt += htmlEncode( v.text() ); } } gpxx = ''; v = $( '.voy-listing-address', $this ).first(); if ( v.length ) { gpxx += ' <gpxx:Address>\n' + ' <gpxx:StreetAddress>' + htmlEncode( v.text() ) + '</gpxx:StreetAddress>\n' + ' </gpxx:Address>\n'; } v = getPhone( '.voy-listing-landline .voy-listing-phone-number', $this ); if ( v ) { gpxx += ' <gpxx:PhoneNumber Category="Phone">' + v + '</gpxx:PhoneNumber>\n'; } v = getPhone( '.voy-listing-tollfree .voy-listing-phone-number', $this ); if ( v ) { gpxx += ' <gpxx:PhoneNumber Category="Tollfree">' + v + '</gpxx:PhoneNumber>\n'; } v = getPhone( '.voy-listing-mobile .voy-listing-phone-number', $this ); if ( v ) { gpxx += ' <gpxx:PhoneNumber Category="Mobile">' + v + '</gpxx:PhoneNumber>\n'; } v = getPhone( '.voy-listing-fax .voy-listing-phone-number', $this ); if ( v ) { gpxx += ' <gpxx:PhoneNumber Category="Fax">' + v + '</gpxx:PhoneNumber>\n'; } v = $( '.voy-listing-email a', $this ).first(); if ( v.length ) { gpxx += ' <gpxx:PhoneNumber Category="Email">' + v.text() + '</gpxx:PhoneNumber>\n'; } v = $this.attr( dataUrl ); if ( v ) { gpxx += ' <gpxx:PhoneNumber Category="URL">' + htmlEncode( v ) + '</gpxx:PhoneNumber>\n'; } text += ' <wpt lat="' + lat + '" lon="' + lon + '">\n' + ' <name>[' + aType + count + '] ' + name + '</name>\n' + ' <type>' + aType + '</type>\n' + ' <extensions>\n' + // ' <color>' + color + '</color>\n' + ' <gpxx:WaypointExtension xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3">\n' + ' <gpxx:DisplayColor>' + color + '</gpxx:DisplayColor>\n' + ' <gpxx:DisplayMode>SymbolAndName</gpxx:DisplayMode>\n' + gpxx + ' </gpxx:WaypointExtension>\n' + ' </extensions>\n'; if ( desc ) { text += ' <desc>' + desc + '</desc>\n'; } if ( cmt ) { text += ' <cmt>' + cmt + '</cmt>\n'; } text += ' </wpt>\n'; } }); text += writeTracks(); if ( !text ) { return ''; } return '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n' + '<gpx version="1.1" creator="Wikivoyage"\n' + ' xmlns="http://www.topografix.com/GPX/1/1"\n' + ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' + ' xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"\n' + ' xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\n' + ' http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www8.garmin.com/xmlschemas/GpxExtensions/v3/GpxExtensionsv3.xsd">\n\n' + ' <metadata>\n' + ' <name>' + htmlEncode( pageTitle ) + '</name>\n' + ' <desc>' + messages.gpxFileDescr + '</desc>\n' + ' <author>\n' + ' <name>Wikivoyage</name>\n' + ' </author>\n' + ' <copyright>\n' + // ' <license>https://creativecommons.org/publicdomain/zero/1.0/</license>\n' + ' <license>https://creativecommons.org/licenses/by-sa/3.0/</license>\n' + // desc is CC-by-sa 3.0 ' </copyright>\n' + ' <bounds minlat="'+ minlat + '" maxlat="' + maxlat + '" minlon="' + minlon +'" maxlon="' + maxlon + '"></bounds>\n' + ' </metadata>\n\n' + text + '</gpx>'; }; const createFile = () => { const downloadText = getText(); if ( !downloadText ) { return; } let fileName = pageTitle + '_' + pageLang + '.gpx'; fileName = fileName.replace( / |:|\/|\\/gi, '_' ); const image = $( '<img>', { class: 'voy-indicator-img', src: isMinerva ? imgSrcMinerva : imgSrc, width: isMinerva ? '15' : '25', height: isMinerva ? '20' : '25' }); if ( isMinerva ) { image.css( { 'margin-left': '3px' } ); // = ( 20 - 15 ) / 2 } let indicator = $( '<a>', { id: 'mw-indicator-i3-gpx', class: 'mw-indicator', /* evtl + cdx-button */ title: messages.gpxTitle, 'data-version': version } ) .css( { display: 'inline-block' } ) .append( image ) .attr( { href: makeFile( downloadText ), download: fileName } ); if ( isMinerva ) { // mobile view indicator.append( $( `<span>${messages.gpxLabel}</span>` ) ); indicator = $( '<li></li>', { id: 'page-actions-poi2gpx', class: 'page-actions-menu__list-item' } ) .append( indicator ); $( minervaPageActionsSelector ).after( indicator ); } else { const indicators = $( '.mw-indicators' ).first(); // always on desktop let geoIndicator; // international version: only: // indicators.prepend( indicator ); indicators.each( function() { geoIndicator = $( '#mw-indicator-i3-geo', $( this ) ); if ( geoIndicator.length ) { geoIndicator.after( indicator ); } else { $( this ).prepend( indicator ); } }); } }; const allowedForCurrentPage = () => { const namespace = mw.config.get( 'wgNamespaceNumber' ); return allowedNamespaces.includes( namespace ) && mw.config.get( 'wgAction' ) == 'view'; }; const init = () => { if ( !allowedForCurrentPage() ) { return; } if ( typeof Blob === 'undefined' ) { // very old browsers return; } setupMessages(); getKartographerLiveData(); // calls createFile }; init(); } ( jQuery, mediaWiki ) ); //</nowiki> pr29xia2ozcn1ngeayx4mxx9pjkv194 MediaWiki:Gadget-MapTools.js 8 1463 22111 18327 2026-05-20T12:59:16Z LiMr 96 aktualizace na novější verzi 22111 javascript text/javascript //<nowiki> /********************************************************************/ // Přeneseno z https://de.wikivoyage.org/wiki/MediaWiki:Gadget-MapTools.js /***************************************************************************** * mapTools v2.2, 2026-04-01 * Several map creation and supporting tools * Original author: Roland Unger * Support of desktop and mobile views * Documentation: https://de.wikivoyage.org/wiki/Wikivoyage:Gadget-MapTools.js * License: GPL-2.0+, CC-by-sa 3.0 ****************************************************************************/ /* eslint-disable mediawiki/class-doc */ ( function( $, mw ) { 'use strict'; // technical constants const version = '2026-04-01', dataLat = 'data-lat', dataLon = 'data-lon', dataZoom = 'data-zoom', dataName = 'data-name', dataHeight = 'data-height', dataOverlays = 'data-overlays', fallbackLang = 'en'; // technical constants const maxZoomLevel = 19, defaultMaplinkZoomLevel = 17, defaultMapZoomLevel = 14, defaultProperties = { 'stroke-width': 2, 'fill-opacity': 0.5 }, indicatorSelector = '.voy-coord-indicator', indicatorCoordsSelector = '.voy-coords a', indicatorGlobeImgSrc = 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Earth_-_The_Noun_Project.svg/20px-Earth_-_The_Noun_Project.svg.png', indicatorMapContainerId = 'voy-topMap', fullScreenContainerId = 'voy-fullScreenMap', mapframeContainerSelector = '.mw-kartographer-container', mapframeMapSelector = '.mw-kartographer-map', markerSelector = '.vcard', // wrapper selector of a single marker or listing kartographerSelector = '.mw-kartographer-maplink', nameClass = 'voy-listing-name', imageClass = 'voy-listing-image', footCaptionSelector = '.oo-ui-windowManager-fullscreen .mw-kartographer-captionfoot', captionMarkerClass = 'voy-caption-marker', captionInverseMarkerClass = 'voy-caption-marker-invers', minervaPageActionsSelector = '.page-actions-menu #page-actions-edit'; // strings depending on page content language const wikiStrings = { de: { defaultShow: '["Maske","Track","Aktivität","Anderes","Anreise","Ausgehen","Aussicht","Besiedelt","Fehler","Gebiet","Gesundheit","Kaufen","Küche","Natur","Religion","Sehenswert","Unterkunft","aquamarinblau","cosmos","gold","hellgrün","orange","pflaumenblau","rot","silber","violett"]', defaultGroupName: 'Karte', mask: 'Maske', track: 'Track' }, en: { defaultShow: '["mask","around","buy","city","do","drink","eat","go","listing","other","see","sleep","vicinity","view","black","blue","brown","chocolate","forestgreen","gold","gray","grey","lime","magenta","maroon","mediumaquamarine","navy","orange","plum","purple","red","royalblue","silver","steelblue","teal"]', defaultGroupName: 'map', mask: 'mask', track: 'track' }, es: { defaultShow: '["máscara","sendero","área","beber","comer","comprar","dormir","error","habitadas","hacer","ir","otro","ver","vista","aguamarina","ciruela","cosmos","oro","lima","naranja","violeta","plata","rojo"]', defaultGroupName: 'mapa', mask: 'máscara', track: 'sendero' }, fr: { defaultShow: '["aller","destination","diplomatie","loger","manger","sortir","ville","voir","mask","around","buy","city","do","drink","eat","go","listing","other","see","sleep","vicinity","view","black","blue","brown","chocolate","forestgreen","gold","gray","grey","lime","magenta","maroon","mediumaquamarine","navy","orange","plum","purple","red","royalblue","silver","steelblue","teal"]', defaultGroupName: 'carte', mask: 'mask', track: 'piste' }, it: { defaultShow: '["mask","around","buy","city","do","drink","eat","go","listing","other","see","sleep","vicinity","view","black","blue","brown","chocolate","forestgreen","gold","gray","grey","lime","magenta","maroon","mediumaquamarine","navy","orange","plum","purple","red","royalblue","silver","steelblue","teal"]', defaultGroupName: 'mappa', mask: 'mask', track: 'traccia' } }; // strings depending on user language const userStrings = { de: { closeButtonTitle: 'Schließen', indicatorActionLabel: 'Karte', indicatorButtonTitle: 'Klick öffnet oder schließt die Karte für $1', magnifyButtonTitle: 'Karte vergrößern', mapCenter: 'Kartenzentrum', mapOf: 'Karte von $1' }, en: { closeButtonTitle: 'Close', indicatorActionLabel: 'Map', indicatorButtonTitle: 'Click to open or close the map of $1', magnifyButtonTitle: 'Enlarge map', mapCenter: 'Map center', mapOf: 'Map of $1' }, es: { closeButtonTitle: 'Cerrar', indicatorActionLabel: 'Mapa', indicatorButtonTitle: 'Haga clic para abrir o cerrar el mapa de $1', magnifyButtonTitle: 'Aumentar mapa', mapCenter: 'Centro del mapa', mapOf: 'Mapa de $1' }, fr: { closeButtonTitle: 'Fermer', indicatorActionLabel: 'Carte', indicatorButtonTitle: 'Cliquez pour ouvrir ou fermer le carte de $1', magnifyButtonTitle: 'Agrandir la carte', mapCenter: 'Centre de la carte', mapOf: 'Carte de $1' }, it: { closeButtonTitle: 'Chiudi', indicatorActionLabel: 'Mappa', indicatorButtonTitle: 'Clicca per aprire o chiudere la mappa di $1', magnifyButtonTitle: 'Ingrandisci mappa', mapCenter: 'Centro mappa', mapOf: 'Mappa di $1' } }; // internal use const $body = $( 'body' ), pageLang = mw.config.get( 'wgPageContentLanguage' ), userLang = mw.config.get( 'wgUserLanguage' ), pageTitle = mw.config.get( 'wgTitle' ), articlePath = mw.config.get( 'wgArticlePath' ), thumbPath = '//upload.wikimedia.org/wikipedia/commons/thumb/', scriptUrl = mw.format( 'https://wikivoyage.toolforge.org/w/data/$1-articles.js', pageLang ), isMinerva = mw.config.get( 'skin' ) === 'minerva'; // mobile view let defaultShowArray, messages = {}; // storing GeoJSON data let data = {}; // array of objects: { name: group.name, attribution: attributions } let groups = [], multiPointUsed = false; // copying translation strings to messages depending on chain languages const addMessages = ( strings, chain ) => { for ( let i = chain.length - 1; i >= 0; i-- ) { if ( strings.hasOwnProperty( chain[ i ] ) ) { $.extend( messages, strings[ chain[ i ] ] ); } } }; // copying translation strings to messages const setupMessages = () => { addMessages( wikiStrings, [ pageLang, fallbackLang ] ); const chain = ( userLang == pageLang ) ? [ pageLang, fallbackLang ] : [ userLang, pageLang, fallbackLang ]; addMessages( userStrings, chain ); }; // creating a Kartographer map const createMap = ( id, center, zoom, caption, options, bgColor, textColor ) => { mw.loader.using( [ 'ext.kartographer.box' ] ).then( function() { const $id = $( '#' + id ); // for simple full-screen map if ( !options.withDialog && options.isFullScreen ) { $body.css( { overflow: 'hidden' } ); $id.css( { position: 'fixed', height: '100%', width: '100%', top: 0, left: 0, 'z-index': 101 } ); // vector skin } // creating base map // fortunately ext.kartographer.box is not validating the // GeoJSON against the GeoJSON+simplestyle schema // as it is done by maplink/mapframe tags // https://github.com/mapbox/simplestyle-spec/tree/master/1.1.0 const kartoBox = require( 'ext.kartographer.box' ), map = kartoBox.map( { container: $id[ 0 ], center: center, zoom: zoom, allowFullScreen: options.allowFullScreen, alwaysInteractive: true, captionText: caption, fullscreen: options.isFullScreen, featureType: options.featureType } ); // following line is necessary for proper loading of // map-dialog sidebar map.initView( center, zoom ); // adding markers by group names to separate layers let group, i, j, layerOptions; if ( options.withData && groups.length ) { for ( i = 0; i < options.show.length; i++ ) { for ( j = 0; j < groups.length; j++ ) { group = groups[ j ]; if ( group.name === options.show[ i ] ) { layerOptions = { name: group.name }; if ( group.attribution !== '' ) { layerOptions.attribution = group.attribution; } map.addGeoJSONLayer( data[ group.name ], layerOptions ); break; } } } } // adding dialog to full-screen map if ( options.withDialog ) { $id.addClass( 'mw-kartographer-mapDialog-map' ); mw.loader.using( 'ext.kartographer.dialog' ).done( function() { map.doWhenReady( function() { require( 'ext.kartographer.dialog' ).render( map ); } ); } ); } else { // adding Close control to non-full-screen map if required if ( options.withClose ) { const controls = $( '.leaflet-top.leaflet-right', $id ), control = $( '<div class="leaflet-bar leaflet-control-static leaflet-control"></div>' ) .append( $( '<a class="voy-icon-close"></a>', { title: messages.closeButtonTitle, role: 'button', 'aria-disabled': 'false' } ) .click( function() { $id.remove(); if ( options.isFullScreen ) { $body.css( { overflow: 'auto' } ); } } ) ); controls.prepend( control ); } // adding Nearby and Layers controls using Kartographer.js if ( options.withControls ) { mw.hook( 'wikipage.maps' ).fire( map ); } } map.doWhenReady( function() { // remove inert attribute $id.removeAttr( 'inert' ); if ( bgColor && options.withDialog ) { setTimeout( function() { const footCaption = $( footCaptionSelector ); if ( footCaption.length ) { const captionArray = footCaption.text().split("​:"), classes = captionMarkerClass; footCaption.html( mw.format( '<span class="$1" style="background-color: $2; color: $3">$4</span>$5', classes, bgColor, textColor, captionArray[ 0 ], captionArray[ 1 ] || '' ) ); } }, 700); } } ); } ); }; // creating GeoJSON data separated by group const singleDataset = ( bgColor, symbol, title, lat, lon, description, group ) => { if ( !data.hasOwnProperty( group ) ) { data[ group ] = []; } data[ group ].push( { 'type': 'Feature', properties: { 'marker-color': bgColor, 'marker-size': 'medium', 'marker-symbol': symbol ? symbol.toLowerCase() : symbol, title: title, description: description }, geometry: { 'type': 'Point', coordinates: [ lon, lat ] } } ); }; // Getting GeoJSON data sets from external sources (OSM, Commons) const getGeoJSON = ( obj ) => { const world = [ [ [ 3600, -180 ], [ 3600, 180 ], [ -3600, 180 ], [ -3600, -180 ], [ 3600, -180 ] ] ]; let promise, coordinates, feature, geometry, i, j, properties = obj.properties; // for all but not for 'page' promise = $.ajax( { // instead of $.getJSON dataType: 'json', url: obj.url, timeout: 3000 } ).then( function( geoJSON ) { switch ( obj.service ) { case 'page': if ( geoJSON.jsondata && geoJSON.jsondata.data ) { $.extend( obj, geoJSON.jsondata.data ); } break; case 'geomask': coordinates = world; for ( i = 0; i < geoJSON.features.length; i++ ) { geometry = geoJSON.features[ i ].geometry; if ( !geometry ) { continue; } // push only first polygon switch ( geometry.type ) { case 'Polygon': coordinates.push( geometry.coordinates[ 0 ] ); break; case 'MultiPolygon': for ( j = 0; j < geometry.coordinates.length; j++ ) { coordinates.push( geometry.coordinates[ j ][ 0 ] ); } } } obj.type = 'Feature'; obj.geometry = { type: 'Polygon', coordinates: coordinates }; if ( !properties ) { properties = defaultProperties; } if ( $.isEmptyObject( obj.properties ) ) { obj.properties = properties; } else { obj.properties = $.extend( {}, properties, obj.properties ); } break; case 'geoline': case 'geoshape': $.extend( obj, geoJSON ); if ( properties ) { for ( i = 0; i < obj.features.length; i++ ) { feature = obj.features[ i ]; if ( $.isEmptyObject( feature.properties ) ) { feature.properties = properties; } else { feature.properties = $.extend( {}, properties, feature.properties ); } } } } }, function() { // failed. Do nothing. } ); return promise; }; // Creating attribution strings const getAttribution = ( obj ) => { let link = ''; switch ( obj.service ) { case 'page': const url = new URL( obj.url, location.origin ), title = url.searchParams.get( 'title' ); link = mw.msg( 'project-localized-name-commonswiki' ) + ': ' + '<a target="_blank" href="' + '//commons.wikimedia.org/wiki/Data:' + encodeURI( title ) + '">' + title + '</a>'; break; default: // other services } return link; }; // getting Kartographer live data const getKartographerLiveData = () => { let group, i, obj, promiseArray = [], attributions, link; data = mw.config.get( 'wgKartographerLiveData' ); if ( data ) { groups = []; // start with empty global array for ( group in data ) { // ignoring empty groups if ( data[ group ].length ) { attributions = []; for ( i = 0; i < data[ group ].length; i++ ) { obj = data[ group ][ i ]; if ( obj.geometry && obj.geometry.type === 'MultiPoint' ) { multiPointUsed = true; } // expand external data if ( obj.type === 'ExternalData' && obj.url ) { promiseArray.push( getGeoJSON( obj ) ); } if ( obj.service ) { link = getAttribution( obj ); if ( link !== '' ) { attributions.push( link ); } } } attributions = attributions.join( ', ' ); groups.push( { name: group, attribution: attributions } ); } } } // wait for getting all external data // regardless of failures, addMapTools() will be executed if ( data && typeof Promise !== 'undefined' ) { Promise.all( promiseArray ) .then( function() { addMapTools(); } ) // initialization also in case of failures // maybe external data are not shown .catch( function() { addMapTools(); } ); } else { addMapTools(); // for really old browsers } }; // returning zoom parameter string as a valid number const getZoom = ( s, defaultValue ) => { const zoom = ( typeof s == 'string' ) ? parseInt( s ) : -1; if ( zoom < 0 || zoom > maxZoomLevel ) { return defaultValue || defaultMapZoomLevel; } return zoom; }; const makeContainer = ( id ) => { $( '#' + id ).remove(); return $( '<div></div>', { id: id, role: 'dialog', 'data-version': version } ); }; // displaying a map by clicking the geo-indicator button const indicatorMap = () => { let indicator = $( indicatorSelector ).first(); if ( !indicator.length ) { return; } if ( !data ) { data = {}; groups = []; defaultShowArray.push( messages.defaultGroupName ); } $( indicatorCoordsSelector ).attr( 'target', '_blank' ); const id = indicatorMapContainerId, options = { withClose: true, withControls: true, withData: true, show: defaultShowArray, withDialog: false, allowFullScreen: true, isFullScreen: false, featureType: 'mapframe' }; const zoom = getZoom( indicator.attr( dataZoom ) ), lat = indicator.attr( dataLat ), lon = indicator.attr( dataLon ), center = [ lat, lon ]; // no POIs --> show blue map-center marker if ( !groups.length ) { singleDataset( '#3366cc', '', messages.mapCenter, lat, lon, '', messages.defaultGroupName ); groups = [ { name: messages.defaultGroupName, attribution: '' } ]; } // add or modify indicator action buttons const mapTitle = mw.format( messages.mapOf, pageTitle ); if ( isMinerva ) { // mobile view // add indicator action button and event handler const indicatorImg = $( '<img>', { class: 'voy-indicator-img', src: indicatorGlobeImgSrc, width: '20', height: '20' } ); indicator = $( '<a>', { id: 'mw-indicator-i3-geo', title: mw.format( messages.indicatorButtonTitle, pageTitle ), class: 'mw-indicator', // cdx-button href: '#' } ) .css( { display: 'inline-block' } ) .append( indicatorImg ) .append( $( `<span>${messages.indicatorActionLabel}</span>` ) ); indicator = $( '<li>', { id: 'page-actions-i3-geo', class: 'page-actions-menu__list-item' } ) .append( indicator ) .click( function() { $( '#bodyContent' ).prepend( makeContainer( id ) ); createMap( id, center, zoom, mapTitle, options ); } ); $( minervaPageActionsSelector ).after( indicator ); } else { // desktop views // replace indicator image and add an event handler $( indicatorSelector + ' .voy-map-globe-default' ) .css( { display: 'none' } ); $( indicatorSelector + ' .voy-map-globe-js' ) .css( { display: 'inline', cursor: 'pointer' } ) .attr( 'title', mw.format( messages.indicatorButtonTitle, pageTitle ) ) .click( function() { const container = $( '#' + id ); if ( container.length ) { container.remove(); } else { $( '#contentSub' ).after( makeContainer( id ) ); createMap( id, center, zoom, mapTitle, options ); } } ); } }; // returning show parameter string as an array const getShow = ( s ) => { return ( s ) ? JSON.parse( s ) : defaultShowArray; }; // replace the Maplink links by MapTools to show Wikivoyage controls const replaceMaplinks = () => { const links = $( kartographerSelector ); if ( !links.length || multiPointUsed ) { return; } const id = fullScreenContainerId, options = { withClose: true, withControls: true, withData: true, show: defaultShowArray, withDialog: true, allowFullScreen: false, isFullScreen: true, featureType: 'maplink' }; links.each( function() { const $this = $( this ); $this.attr( 'href', '#' ) .css( { cursor: 'pointer', 'pointer-events': 'auto', 'text-decoration': 'none' } ); $this.click( function( event ) { event.stopImmediatePropagation(); event.preventDefault(); // marker could contain an image -> closest const target = $( event.target ).closest( kartographerSelector ), wrapper = target.closest( markerSelector ), lat = target.attr( dataLat ), lon = target.attr( dataLon ), center = [ lat, lon ], zoom = getZoom( target.attr( dataZoom ), defaultMaplinkZoomLevel ), bgColor = target.css( 'background-color' ), textColor = target.css( 'color' ); let name = wrapper.attr( dataName ) || '', symbolText = target.text(); if ( name === '' ) { name = symbolText; } else if ( name !== '' && symbolText !== '' ) { name = symbolText + '​: ' + name; } options.show = getShow( target.attr( dataOverlays ) ); $body.append( makeContainer( id ) ); createMap( id, center, zoom, name, options, bgColor, textColor ); return false; // don't follow the link } ); } ); }; // adding a magnify button to Kartographer container const addMagnifyButton = () => { const maps = $( mapframeContainerSelector ); if ( !maps.length || multiPointUsed ) { return; } const id = fullScreenContainerId, options = { withClose: true, withControls: true, withData: true, show: defaultShowArray, withDialog: true, allowFullScreen: false, isFullScreen: true, featureType: 'maplink' }; maps.each( function() { const $this = $( this ); // no magnify button if zoom is already maxZoomLevel // not in frameless mode const map = $( mapframeMapSelector, $this ).first(), caption = $( '.thumbcaption', $this ).first(); let zoom = getZoom( map.attr( dataZoom ) ); if ( map.length && caption.length && zoom < maxZoomLevel ) { const link = $( '<a class="internal"></a>' ) .css( { cursor: 'pointer' } ) .attr( 'title', messages.magnifyButtonTitle ) .click( function( event ) { const target = $( event.target ); let map = target.closest( mapframeContainerSelector ); const caption = $( '.thumbcaption', map ).first(), name = caption.text(); // getting initial position from data if lat or lon // or zoom are undefined map = $( mapframeMapSelector, map ).first(); const center = [ map.attr( dataLat ), map.attr( dataLon ) ]; let zoom = Number( map.attr( dataZoom ) ); if ( isNaN( zoom ) ) { zoom = undefined; } else { let zoomIncr = 1; const height = screen.height / map.attr( dataHeight ); if ( height > 4 ) { zoomIncr++; } if ( height > 8 ) { zoomIncr++; } zoom += zoomIncr; if ( zoom > maxZoomLevel ) { zoom = maxZoomLevel; } } options.show = getShow( map.attr( dataOverlays ) ); $body.append( makeContainer( id ) ); createMap( id, center, zoom, name, options ); } ); caption.prepend( $( '<div class="magnify"></div>' ).append( link ) ); } } ); }; // adding all tools // called by getKartographerLiveData() const addMapTools = () => { addMagnifyButton(); indicatorMap(); replaceMaplinks(); }; const init = () => { setupMessages(); defaultShowArray = JSON.parse( messages.defaultShow ); getKartographerLiveData(); // calling addMapTools() }; init(); } ( jQuery, mediaWiki ) ); //</nowiki> 788a1efr20uu1et60d34ymfjv4sepnj MediaWiki:Gadget-MapTools.css 8 1464 22110 18329 2026-05-20T12:55:06Z LiMr 96 aktualizace na novější verzi 22110 css text/css /* Styles for MapTools gadget Version: 2025-12-20 */ /* Mobile-view page-actions menu: for MapTools and Poi2gpx */ .skin-minerva .content ul { list-style: square outside; padding-left: 1em; } .skin-minerva .content .tocUl, .skin-minerva .content .tocUl ul { list-style: none; } .skin-minerva .mw-indicator { margin: 0 !important; padding: 0.5em 0.75em 0 !important; height: 1.85em; color: #54595d !important; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border: 1px solid transparent; border-radius: 2px; font-weight: 500 !important; box-sizing: content-box !important; text-decoration: none !important; } .skin-minerva .mw-indicator:focus { border-color: #3366cc; box-shadow: inset 0 0 0 1px #3366cc,inset 0 0 0 2px #ffffff; outline: 0; } .skin-minerva .mw-indicator:active { border-color: #72777d; box-shadow: none; background-color: rgba(0,36,73,0.08235294); } .skin-minerva .mw-indicator:hover { background-color: rgba(0,0,0,0.03); } .skin-minerva .mw-indicator img { vertical-align: text-bottom; margin-right: 10px; } @media (max-width: 1119px) { .skin-minerva .mw-indicator { width: 1.25em; color: transparent !important; } .skin-minerva .mw-indicator img { margin-right: 0; vertical-align: 0; } } /* Map container */ #voy-topMap { height: 400px; border: 1px solid #c8ccd1; margin: 0.7em 0 1em; } #voy-articles-map { height: 600px; border: 1px solid #c8ccd1; } @media (max-width: 1300px) { /* laptop and smartphone support */ #voy-articles-map { height: 450px; } } @media (max-width: 800px) { #voy-articles-map { height: 350px; } } @media (max-width: 600px) { #voy-articles-map { height: 300px; } } /* Caption marker */ .voy-caption-marker { font-size: 80%; font-weight: bold; text-align: center; display: inline-block; min-width: 1em; padding: 0 0.2em 0; border-radius: 3px; } /* Close icon */ #voy-topMap .voy-icon-close, #voy-fullScreenMap .voy-icon-close, #voy-articles-map .voy-icon-close { background-image: url(/w/load.php?modules=oojs-ui.styles.icons-interactions&image=close&format=rasterized&lang=de&skin=vector&version=12ligfd); background-image: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2220%22 height=%2220%22 viewBox=%220 0 20 20%22%3E%3Ctitle%3Eclose%3C/title%3E%3Cpath d=%22M4.34 2.93l12.73 12.73-1.41 1.41L2.93 4.35z%22/%3E%3Cpath d=%22M17.07 4.34L4.34 17.07l-1.41-1.41L15.66 2.93z%22/%3E%3C/svg%3E"); background-position: center center; } /* Border of the map itself */ .mw-kartographer-container.thumb:not(.mw-kartographer-full) .thumbinner > .mw-kartographer-map { border: 1px solid #ccc; box-sizing: border-box; } /* Magnify symbol */ .mw-kartographer-container .magnify { /* magnify button of Minerva skin */ float: right; margin-left: 3px; margin-right: 0; display: block !important; } .mw-kartographer-container div.magnify a { background-image: url(/w/resources/src/mediawiki.skinning/images/magnify-clip-ltr.png?4f704); background-image: linear-gradient(transparent,transparent),url("data:image/svg+xml,%3C%3Fxml version=%221.0%22 encoding=%22UTF-8%22 standalone=%22no%22%3F%3E%0A%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 11 15%22 width=%2215%22 height=%2211%22%3E%0A %3Cg id=%22magnify-clip%22 fill=%22%23fff%22 stroke=%22%23000%22%3E%0A %3Cpath id=%22bigbox%22 d=%22M1.509 1.865h10.99v7.919h-10.99z%22/%3E%0A %3Cpath id=%22smallbox%22 d=%22M-1.499 6.868h5.943v4.904h-5.943z%22/%3E%0A %3C/g%3E%0A%3C/svg%3E%0A") !important; text-indent: 15px; white-space: nowrap; overflow: hidden; width: 15px; height: 11px; text-decoration: none; } /* Kartographer-Popup */ .leaflet-popup-content { width: 141px !important; } .leaflet-popup-content .marker-title { font-weight: normal; } .leaflet-popup-content img { display: block; width: 100% !important; height: auto !important; } .leaflet-container img { border: none; } /* Layers control */ .mw-kartographer-interactive .leaflet-control-layers-expanded { overflow-x: hidden; overflow-y: auto; width: 200px; } @media print { .leaflet-bar, .leaflet-control { display: none; } } crqurvcvndjnben24cexif11k6sxbgg MediaWiki:Gadget-MarkerTooltip.js 8 1465 22108 20852 2026-05-20T12:51:08Z LiMr 96 aktualizace na novější verzi 22108 javascript text/javascript //<nowiki> /********************************************************************/ // Přeneseno z https://de.wikivoyage.org/wiki/MediaWiki:Gadget-MarkerTooltip.js /*************************************************************************** * MarkerTooltip.js v1.6, 2026-04-06 * Displays an extended marker tooltip on mouse over on desktops * or on click on smartphones * Displays tooltip for abbreviations on smartphones * Original author: Roland Unger * Support of both desktop and mobile views * Documentation: https://de.wikivoyage.org/wiki/Wikivoyage:Gadget-MarkerTooltip.js * License: GPL-2.0+, CC-by-sa 3.0 ***************************************************************************/ /* eslint-disable mediawiki/class-doc */ ( function ( $ ) { 'use strict'; const version = "2026-04-06"; const strings = { de: { hint: 'Click auf den Marker öffnet die Karte direkt.', hint2: 'Bitte nutzen Sie zur Anzeige die Kartendienste.', ch1903: 'CH1903', ch1903Title: 'Es folgt die Koordinate in der Form der Schweizer Landeskoordinaten.', dec: 'Dezimal', decTitle: 'Es folgt die Koordinate in Dezimalform. Über den nebenstehenden Geo-URI-Link kann eine Karten-Anwendung gestartet werden.', geoUriTitle: 'Über diesen Link startet der Browser eine Karten-Anwendung, z.&#x202F;B. Google Maps. Auf vielen Smartphones bereits eingerichtet.', hex: 'GMS', hexTitle: 'Es folgt die Koordinate in der Form Grad-Minuten-Sekunden.', plus: 'Plus Code', plusTitle: 'Es folgt die Koordinate als Plus Code.', anchor: 'Anker', anchorTitle: 'Zeigt den Namen des Vorlagen-Ankers an.', anchorText: 'Der Name des Vorlagen-Ankers lautet:\n\n', clipboard: 'Ablage', clipboardTitle:'Kopiert die nebenstehende Angabe in die Zwischenablage. Insbesondere ältere Browser unterstützten diese Funktion leider nicht.', mapSources: 'Kartendienste', mapSourcesTitle: 'Es folgen verschiedene Listen mit Kartenquellen und -diensten', tools: 'Werkzeuge', toolsTitle: 'Es folgen verschiedene Vorlagen-Werkzeuge', voy: 'Wikivoyage', voyTitle: 'Öffnet eine Wikivoyage-eigene Internetseite, die zahlreiche Kartenquellen und -dienste auflistet.', voyURL: '/w/index.php?title=Special%3AMapsources', wmflabs: 'WMF-Labs', wmflabsTitle: 'Öffnet eine Internetseite von WMF Labs, die zahlreiche Kartenquellen und -dienste auflistet.', wmflabsURL: 'https://tools.wmflabs.org/geohack/geohack.php', EW: 'OW', // international: 'EW' NS: 'NS' }, en: { hint: 'Clicking on the marker directly opens the map.', hint2: 'Please use the map tools for display.', ch1903: 'CH1903', ch1903Title: 'Coordinates are shown in the form of the Swiss national coordinates.', dec: 'Decimal', decTitle: 'Coordinates are shown as decimal values. A map application can be started via the adjacent Geo-URI link.', geoUriTitle: 'The browser starts a map application using this link, e.&#x202F;g. Google Maps. Already set up on many smartphones.', hex: 'DMS', hexTitle: 'Coordinates are shown as degree-minutes-seconds.', plus: 'Plus Code', plusTitle: 'Coordinates are shown as Plus Code.', anchor: 'Anchor', anchorTitle: 'Shows the name of the template anchor.', anchorText: 'The name of the template anchor is:\n\n', clipboard: 'Clipboard', clipboardTitle:'Copies the adjacent information to the clipboard. Unfortunately, older browsers do not support this feature.', mapSources: 'Map tools', mapSourcesTitle: 'The following lists with map sources and services are available', tools: 'Tools', toolsTitle: 'The following tools are available', voy: 'Wikivoyage', voyTitle: 'Opens Wikivoyage’s own webpage which lists numerous map sources and services.', voyURL: '/w/index.php?title=Special%3AMapsources', wmflabs: 'WMF Labs', wmflabsTitle: 'Opens a WMF Labs webpage which lists numerous map sources and services.', wmflabsURL: 'https://tools.wmflabs.org/geohack/geohack.php', EW: 'EW', NS: 'NS' }, es: { hint: 'Haga clic aquí para abrir el mapa.', hint2: 'Utilice los servicios de mapas para visualizar.', ch1903: 'CH1903', ch1903Title: 'A esto le sigue la coordenada en forma de coordenadas nacionales suizas.', dec: 'Decimal', decTitle: 'La coordenada sigue en forma decimal. Se puede iniciar una aplicación de mapas a través del enlace Geo-URI adyacente.', geoUriTitle: 'El navegador inicia una aplicación de mapas a través de este enlace, p. ej. mapas de Google. Ya está configurado en muchos teléfonos inteligentes Android.', hex: 'GMS', hexTitle: 'La coordenada sigue en forma de grados-minutos-segundos.', plus: 'Plus Code', plusTitle: 'La coordenada sigue como un código de ubicación abierto.', anchor: 'Ancla', anchorTitle: 'Muestra el nombre del ancla de la plantilla.', anchorText: 'El nombre del ancla de la plantilla es:\n\n', clipboard: 'Portapapeles', clipboardTitle:'Copia la información adyacente al portapapeles. Lamentablemente, los navegadores más antiguos no admiten esta función.', mapSources: 'Instrumentos de mapas', mapSourcesTitle: 'Las siguientes listas con fuentes y instrumentos de mapas están disponibles.', tools: 'Instrumentos', toolsTitle: 'Los siguientes instrumentos están disponibles.', voy: 'Wikiviajes', voyTitle: 'Abre un sitio web de Wikiviajes que enumera numerosas fuentes y instrumentos de mapas.', voyURL: '/w/index.php?title=Special%3AMapsources', wmflabs: 'WMF Labs', wmflabsTitle: 'Abre un sitio web de WMF Labs que enumera numerosas fuentes y instrumentos de mapas.', wmflabsURL: 'https://tools.wmflabs.org/geohack/geohack.php', EW: 'EO', // international: 'EW' NS: 'NS' }, cs: { hint: 'Kliknutím přímo na bod se otevře mapa.', hint2: 'K zobrazení použijte mapové služby.', ch1903: 'CH1903', ch1903Title: 'Souřadnice jsou zobrazeny ve formátu švýcarských národních souřadnic.', dec: 'Desetinný', decTitle: 'Souřadnice jsou zobrazeny jako desetinné hodnoty. Mapová aplikace se spustí přes sousední Geo-URI odkaz.', geoUriTitle: 'Prohlížeč spustí mapovou aplikaci pomocí tohoto odkazu, např. Google Maps. Na mnoha chytrých telefonech už je nastaveno.', hex: 'DMS', hexTitle: 'Souřadnice jsou zobrazeny jako stupně, minuty a sekundy.', plus: 'Plus Code', plusTitle: 'Souřadnice jsou zobrazeny jako Plus Code.', anchor: 'Kotva', anchorTitle: 'Zobrazuje název kotvy šablony.', anchorText: 'Název kotvy šablony je:\n\n', clipboard: 'Zkopírovat', clipboardTitle:'Zkopíruje sousední údaj do schránky. Bohužel tuto možnost nepodporují starší prohlížeče.', mapSources: 'Mapové nástroje', mapSourcesTitle: 'K dispozici jsou následující seznamy s mapovými zdroji a službami', tools: 'Nástroje', toolsTitle: 'K dispozici jsou následující nástroje', voy: 'Wikicesty', voyTitle: 'Otevře webovou stránku Wikicest s mnoha mapovými zdroji a službami.', voyURL: '/w/index.php?title=Special%3AMapsources', wmflabs: 'WMF Labs', wmflabsTitle: 'Otevře webovou stránku WMF Labs s mnoha mapovými zdroji a službami.', wmflabsURL: 'https://tools.wmflabs.org/geohack/geohack.php', EW: 'EW', NS: 'NS' } }; const fallbackLang = 'en', maxZoomLevel = 19; // see also getScaleFromZoom const options = { plusCode: false, ch1903: true }; const classes = { copyMarker: 'voy-copy-marker', idRegex: /vCard_.+/, // see [[Module:Marker_utilities/i18n]], texts.anchor listingTooltip: 'voy-listing-tooltip', listingTooltipMobile: 'voy-listing-tooltip-mobile', withoutMarker: 'voy-without-marker' }; const selectors = { kartographerLink: '.mw-kartographer-maplink', latitude: '.p-latitude', longitude: '.p-longitude', lCoordinates: '.voy-listing-coordinates', lEditButton: '.voy-listing-edit-button button', lInfoButton: '.voy-listing-info-button button', lMap: '.voy-listing-map, .voy-listing-without-marker', lName: '.voy-listing-name', vcard: '.vcard' }; const data = { color: 'data-color', id: 'data-tooltip-id', lat: 'data-lat', lon: 'data-lon', mAttribute: 'data-copy-marker-attribute', mContent: 'data-copy-marker-content', name: 'data-name', region: 'data-region', zoom: 'data-zoom', version: 'data-version' }; // internal use const pageLang = mw.config.get( 'wgPageContentLanguage' ), userLang = mw.config.get( 'wgUserLanguage' ), // isMobile = window.matchMedia( '(any-pointer: coarse)' ).matches && // has touch screen or similar // !window.matchMedia( '(any-pointer: fine)' ).matches, // has mouse isMobile = ( /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test( navigator.userAgent.toLowerCase() ) ), timeouts = []; let messages = {}; const addMessages = ( str, chain ) => { for ( let i = chain.length - 1; i >= 0; i-- ) { if ( str.hasOwnProperty( chain[ i ] ) ) { $.extend( messages, strings[ chain[ i ] ] ); } } }; const setupMessages = () => { const chain = ( userLang == pageLang ) ? [ pageLang, fallbackLang ] : [ userLang, pageLang, fallbackLang ]; addMessages( strings, chain ); }; // Only n digits const round = ( coord, n ) => { const m = Math.pow( 10, n ); return Math.round( coord * m ) / m; }; // Converting decimal to DMS coordinates const toDMS = ( dec, letters ) => { const letter = letters.charAt( ( dec >= 0 ) ? 0 : 1 ), angle = Math.abs( dec ); let deg = Math.floor( angle ), min = ( angle - deg ) * 60, sec = Math.round( ( min - Math.floor( min ) ) * 60 ); min = Math.floor( min ); if ( sec >= 60 ) { sec -= 60; min += 1; } if ( min >= 60 ) { min -= 60; deg += 1; } return `${deg}° ${min}′ ${sec}″ ${letter}`; }; // Converting decimal to CH1903 coordinates // see: https://de.wikipedia.org/wiki/Schweizer_Landeskoordinaten const toCH1903 = ( lat, lon ) => { const ch1903 = { easting: 0, northing: 0, error: true }; if ( lat < 45.5 || lat > 48 || lon < 5.0 || lon > 11 ) { return ch1903; } const phi = ( lat * 3600 - 169028.66 ) / 10000, phi2 = phi * phi, lambda = ( lon * 3600 - 26782.5 ) / 10000, lambda2 = lambda * lambda; ch1903.northing = Math.round( 200147.07 + 308807.95 * phi + 3745.25 * lambda2 + 76.63 * phi2 - 194.56 * lambda2 * phi + 119.79 * phi2 * phi ); ch1903.easting = Math.round( 600072.37 + 211455.93 * lambda - 10938.51 * lambda * phi - 0.36 * lambda * phi2 - 44.54 * lambda2 * lambda ); ch1903.error = false; return ch1903; }; // Converting decimal to Open Location Code (Plus Code) // see: https://en.wikipedia.org/wiki/Open_Location_Code const toPlusCode = ( lat, lon ) => { const codeChars = '23456789CFGHJMPQRVWX', resolutions = [ 20.0, 1.0, 0.05, 0.0025, 0.000125 ]; let code = ''; let modLat = lat; modLat = Math.max( -90, modLat ); modLat = Math.min( modLat, 90 - 0.000025 ); // 0.000025 = resolutions[ 4 ] / 5 [rows] modLat += 90; // starting from 0 let modLon = lon; while ( modLon < -180 ) { modLon += 360; } while ( modLon >= 180 ) { modLon -= 360; } modLon += 180; // starting from 0 // first 10 + 1 digits for ( let i = 0; i < 5; i++ ) { const res = resolutions[ i ]; let digit = Math.floor( modLat / res ); modLat -= digit * res; code += codeChars.charAt( digit ); digit = Math.floor( modLon / res ); modLon -= digit * res; code += codeChars.charAt( digit ); if ( i === 3 ) { code += '+'; } } // last digit const row = Math.floor( 5 * modLat / resolutions[ 4 ] ), col = Math.floor( 4 * modLon / resolutions[ 4 ] ); code += codeChars.charAt( 4 * row + col ); return code; }; const shortenCoordinate = ( coord ) => { return Math.round( coord * 1E5 ) / 1E5; // only 5 decimals }; // zoom level 19 -> 1:1000, 0 -> 500000000 const getScaleFromZoom = ( zoom ) => { const scales = [ 1000, 2000, 4000, 8000, 15000, 35000, 70000, 150000, 250000, 500000, 1000000, 2000000, 4000000, 10000000, 15000000, 35000000, 70000000, 150000000, 250000000, 500000000 ]; if ( zoom >= maxZoomLevel ) { return scales[ 0 ]; } else if ( zoom <= 0 ) { return scales[ scales.length - 1 ]; } return scales[ maxZoomLevel - Math.round( zoom ) ]; }; const copyToClipboard = ( selector, container ) => { const clipboard = $( '<textarea id="mkClipboard"></textarea>' ) .css( { 'width': 1, 'border': 'none', 'opacity': 0 } ); $( 'body' ).append( clipboard ); const text = ( selector !== '.mkClip5' ) ? $( selector, container ).text() : $( '#anchorId', container ).text(); clipboard.val( text ).select(); document.execCommand( 'copy' ); clipboard.remove(); }; const clipboardLink = ( aClass ) => { return aClass ? `[ <a href="javascript:" class="${aClass}" title="${messages.clipboardTitle}">${messages.clipboard}</a> ]` : ''; }; const makeTableRow = ( label, title, clipClass, buttonClass, text ) => { return `<tr><td><span title="${title}">${label}:</span> <span class="${clipClass}">${text}</span></td><td>${clipboardLink( buttonClass )}</td></tr>`; }; const makeContent = ( $origin ) => { let link = $( selectors.kartographerLink, $origin ).first(), lat, lon, withMarker, zoom; if ( link.length ) { lat = round( link.attr( data.lat ), 6 ); lon = round( link.attr( data.lon ), 6 ); zoom = link.attr( data.zoom ); withMarker = true; } else { link = $origin.closest( selectors.vcard ).find( selectors.lCoordinates ); lat = round( $( selectors.latitude, link ).text(), 6 ); lon = round( $( selectors.longitude, link ).text(), 6 ); zoom = 16; withMarker = false; } const latStr = toDMS( lat, messages.NS ), lonStr = toDMS( lon, messages.EW ); const wrapper = $origin.closest( selectors.vcard ), color = wrapper.attr( data.color ), region = wrapper.attr( data.region ) || ''; let name = wrapper.attr( data.name ); if ( !name ) { name = $( selectors.lName, wrapper ).first(); const wikiLink = $( 'a', name ).first(); name = ( wikiLink.length ) ? wikiLink.text() : name = name.text(); } name = encodeURI( name.replace( /\s/g, '+' ) ).replace( /&/g, '%26' ); let params = '&params=' + Math.abs( lat ) + ( lat < 0 ? '_S_' : '_N_' ) + Math.abs( lon ) + ( lon < 0 ? '_W' : '_E' ) + `_scale%3A${getScaleFromZoom( zoom )}_type%3Alandmark_globe%3Aearth`; if ( region !== '' ) { params += '_region%3A' + region; } const ch1903 = toCH1903( lat, lon ), plusCode = toPlusCode( lat, lon ), latDec = shortenCoordinate( lat ), lonDec = shortenCoordinate( lon ); let table = '<table>' + makeTableRow( messages.hex, messages.hexTitle, 'mkClip1', 'mkButton1', latStr + ' ' + lonStr ) + makeTableRow( messages.dec, messages.decTitle, 'mkClip2', 'mkButton2', `<a href="geo:${latDec},${lonDec}" title="${messages.geoUriTitle}">${latDec}, ${lonDec}</a>` ); if ( options.plusCode ) { table += makeTableRow( messages.plus, messages.plusTitle, 'mkClip3', 'mkButton3', `<span class="voy-mkTooltipPlusCode">${plusCode.substr( 0, 4 ) }</span>` + plusCode.substr( 4 ) ); } if ( options.ch1903 && !ch1903.error ) { table += makeTableRow( messages.ch1903, messages.ch1903Title, 'mkClip4', 'mkButton4', `<span title="CH1903 easting">${ch1903.easting}</span> / <span title="CH1903 northing">${ch1903.northing}</span>` ); } const html = [], infobutton = $( selectors.lInfoButton, wrapper ).prop( 'outerHTML' ) || ''; if ( infobutton !== '' ) { html.push( `<span id="infobutton">${infobutton}</span>` ); } const editbutton = $( selectors.lEditButton, wrapper ).prop( 'outerHTML' ) || ''; if ( editbutton !== '' ) { html.push( `<span id="editbutton">${editbutton}</span>` ); } let id = wrapper.attr( 'id' ); id = id && id.match( classes.idRegex ); if ( id ) { const anchor = `<a href="#" id="anchorIdLink" title="${messages.anchorTitle}">${messages.anchor}</a>` + `<span id="anchorId" style="display: none">${id}</span>`; html.push( anchor ); } if ( html.length ) { table += makeTableRow( messages.tools, messages.toolsTitle, 'mkClip5', id ? 'mkButton5' : null, html.join( ' | ' ) ); } table += '</table>'; const mapSources = `<div title="${messages.mapSourcesTitle}">${messages.mapSources}: ` + `<a href="${messages.voyURL + params}&locname=${name}" title="${messages.voyTitle}" target="_blank" rel="noopener">${messages.voy}</a> | ` + `<a href="${messages.wmflabsURL}?pagename=${name}&language=${pageLang + params}" title="${messages.wmflabsTitle}" target="_blank" rel="noopener">${messages.wmflabs}</a>` + '</div>'; return $( '<div class="voy-mkTooltipInner"></div>' ) .css( 'border-left-color', color ) .append( $( '<div class="voy-mkTooltipHint">' + (withMarker ? messages.hint : messages.hint2 ) + '</div>' ) .css( { 'margin-bottom': '0.5em' } ) ) .append( $( table ) ) .append( $( mapSources ) ) .append( $( '<div class="voy-mkTooltipTail"></div>' ) ); }; // setting tooltip position const setTooltipPosition = ( e, tooltip, $this ) => { const tail = $( '.voy-mkTooltipTail', tooltip ), winWidth = $( window ).width(); let left, offset, right, width; if ( e.clientY < $( window ).height() / 2 ) { tooltip.css( 'top', $this.innerHeight() - 4 ) .addClass('voy-mkBelow'); } else { tooltip.css( 'bottom', $this.innerHeight() - 4 ) .addClass('voy-mkAbove'); } if ( e.clientX < winWidth / 2 ) { tooltip.css( 'left', $this.innerWidth() / 2 - 16 ) .addClass('voy-mkLeft'); if ( isMobile ) { offset = tooltip.offset(); right = offset.left + tooltip.outerWidth(); if ( right > winWidth - 1 ) { left = offset.left - ( right - winWidth ) - 2; if ( left < 2 ) { left = 2; } width = tooltip.innerWidth(); tooltip.offset( { top: offset.top, left: left } ); tooltip.innerWidth( width ); width = offset.left - left; offset = tail.offset(); offset.left += width; tail.offset( offset ); } } } else { tooltip.css( 'right', $this.innerWidth() / 2 - 13 ) .addClass('voy-mkRight'); if ( isMobile ) { offset = tooltip.offset(); left = offset.left; if ( left < 2 ) { width = tooltip.innerWidth(); tooltip.offset( { top: offset.top, left: 2 } ); tooltip.innerWidth( width ); offset = tail.offset(); offset.left += left; tail.offset( offset ); } } } }; const showMarkerTooltip = ( e ) => { const $this = $( e.target ).closest( '.' + classes.listingTooltip ), id = $this.attr( data.id ), isCopyMarker = $this.hasClass( classes.copyMarker ), wrapper = $this.closest( selectors.vcard ), withoutMarker = wrapper.hasClass( classes.withoutMarker ), triggerWrapper = withoutMarker || !isCopyMarker; let $origin = $this; e.stopPropagation(); if ( isCopyMarker ) { // getting from original marker const attr = $this.attr( data.mAttribute ), content = $this.attr( data.mContent ); $origin = $( `*[${attr}="${content}"]` ).first(); } const tooltip = $( `<div class="voy-mkTooltip" role="tooltip" ${data.version}="${version}"/>` ) .append( makeContent( $origin ) ); if ( isMobile ) { tooltip.addClass( 'voy-mkTooltipMobile' ); } else { tooltip.hide(); // later fade-in; } $this.append( tooltip ); setTooltipPosition( e, tooltip, $this ); $( '.mkButton1', tooltip ) .click( function() { copyToClipboard( '.mkClip1', tooltip ); } ); $( '.mkButton2', tooltip ) .click( function() { copyToClipboard( '.mkClip2', tooltip ); } ); $( '.mkButton3', tooltip ) .click( function() { copyToClipboard( '.mkClip3', tooltip ); } ); $( '.mkButton4', tooltip ) .click( function() { copyToClipboard( '.mkClip4', tooltip ); } ); $( '.mkButton5', tooltip ) .click( function() { copyToClipboard( '.mkClip5', tooltip ); } ); $( '#anchorIdLink', tooltip ) .click( function() { const alertText = messages.anchorText + $( '#anchorId', tooltip ).text(); removeAllTooltips(); alert( alertText ); } ); $( '#infobutton', tooltip ) .click( function( e ) { e.stopImmediatePropagation(); $( selectors.lInfoButton, triggerWrapper ? wrapper : $origin ).trigger( 'click' ); removeAllTooltips(); } ); $( '#editbutton', tooltip ) .click( function( e ) { e.stopImmediatePropagation(); $( selectors.lEditButton, triggerWrapper ? wrapper : $origin ).trigger( 'click' ); removeAllTooltips(); } ); if ( isMobile ) { // removing tooltip after 10 sec in mobile mode timeouts[ id ] = setTimeout( function() { removeTooltip( $this ); }, 10000 ); $( 'body' ).click( handleOutsideClick ); } else { // fading-in hidden tooltip in desktop mode setTimeout( function() { tooltip.fadeIn( 500 ); }, 300 ); } return; }; // Click event handler if clicked outside any tooltip const handleOutsideClick = ( event ) => { if ( !$( event.target ).closest( '.voy-mkTooltip' ).length && $( '.voy-mkTooltip' ).is( ':visible' ) ) { removeAllTooltips(); } }; const removeTooltip = ( marker ) => { const id = marker.attr( data.id ); if ( id ) { clearTimeout( timeouts[ id ] ); } $( '.voy-mkTooltip', marker ).remove(); $( '.voy-mkTooltipButton', marker ).text( '▼' ); }; const removeAllTooltips = () => { if ( isMobile ) { $( 'body' ).off( 'click', handleOutsideClick ); } const markers = $( '.' + classes.listingTooltip ).add( $( 'abbr' ) ); markers.each( function() { removeTooltip( $( this ) ); }); }; const showMobileMarker = ( e ) => { const $this = $( e.target ).closest( '.voy-mkTooltipButton' ), text = $this.text(); removeAllTooltips(); if ( text === '▼' ) { $this.text( '▲' ); showMarkerTooltip( e ); } }; const initMarkerTooltip = () => { $( selectors.lMap ).addClass( classes.listingTooltip ) .css( { position: 'relative' } ); if ( isMobile ) { $( selectors.lMap ).addClass( classes.listingTooltipMobile ); } const markers = $( '.' + classes.listingTooltip ) .removeAttr( 'title' ); let id = 0; // setting id for timeout handler markers.each( function() { $( this ).attr( data.id, 'tt' + id ); id += 1; } ); if ( isMobile ) { const mobileMarker = $( '<span class="voy-mkTooltipButton">▼</span>' ) .click( function( e ) { showMobileMarker( e ); }); markers.append( mobileMarker ); } else { markers.mouseenter( function( e ) { showMarkerTooltip( e ); }) .mouseleave( function( e ) { $( '.voy-mkTooltip' ).remove(); }); } }; const initAbbrTooltip = () => { const abbr = $( 'abbr' ) .css( { 'position': 'relative', 'cursor': 'pointer' } ); let id = 0; // setting id for timeout handler abbr.each( function() { $( this ).attr( data.id, 'at' + id ); id += 1; } ); abbr.click( function( e ) { e.stopPropagation(); const $this = $( e.target ).closest( 'abbr' ), id = $this.attr( data.id ); let tooltip = $( '.voy-mkTooltip', $this ); removeAllTooltips(); if ( tooltip.length === 0 ) { const title = $this.attr( 'title' ); if ( title ) { const div = $( `<div class="voy-mkTooltipInner voy-mkTooltipMaxWidth">${title}</div>` ) .append( $( '<div class="voy-mkTooltipTail"></div>' ) ); tooltip = $( '<div class="voy-mkTooltip voy-mkTooltipMobile" role="tooltip"></div>' ) .append( div ); $this.append( tooltip ); setTooltipPosition( e, tooltip, $this ); timeouts[ id ] = setTimeout( function() { removeTooltip( $this ); }, 10000 ); $( 'body' ).click( handleOutsideClick ); } } } ); }; const init = () => { setupMessages(); initMarkerTooltip(); if ( isMobile ) { $( 'body' ).addClass( 'voy-is-mobile' ); initAbbrTooltip(); } }; init(); } ( jQuery ) ); //</nowiki> fzpnc6t4guqhb6b8rx8z28smqorq7qe MediaWiki:Gadget-MarkerTooltip.css 8 1466 22109 18335 2026-05-20T12:53:07Z LiMr 96 aktualizace na novější verzi 22109 css text/css /* Marker tooltip styles Version: 2026-04-23 */ /* Styles for tooltip box */ .voy-mkTooltip { position: absolute; background-color: transparent; color: var(--color-base,#202122); font-weight: normal; font-size: 90%; font-style: normal; line-height: 1.25em; text-align: left; z-index: 10; /* markers: z-index: 2; wikiEditor-ui-toolbar: z-index: 7 */ cursor: auto; } .voy-mkTooltipMobile { line-height: 1.5em; } .voy-mkTooltipInner { position: relative; background-color: #ffffe3; border: 1px solid #808080; border-left-width: 4px; border-radius: 3px; box-shadow: 0 0 2px 1px rgba(0,0,0,0.5); padding: 2px 4px; } .voy-mkTooltipInner div, .voy-mkTooltipInner table { white-space: nowrap; } .voy-mkTooltipInner table { width: 100% !important; /* !important for Minerva Skin */ display: table !important; margin: 0 !important; border-collapse: collapse; border-spacing: 0; border-style: none; } .voy-mkTooltipInner table td { padding: 0; text-align: left; border-style: none; } .voy-mkTooltipInner table td:last-child { padding-left: 2em; text-align: right; font-size: 80%; } .voy-mkTooltipMaxWidth { max-width: 12.5em; width: -moz-max-content; width: -webkit-max-content; width: max-content; } /* Edit and info buttons */ .voy-mkTooltipInner button { border: none; background-color: transparent; font-family: sans-serif; font-size: 1em; cursor: pointer; padding: 0; color: var(--color-progressive,#36c); } .voy-mkTooltipInner button:hover, .voy-mkTooltipInner button:focus, .voy-mkTooltipInner button:active { text-decoration: underline; color: var(--color-progressive--hover,#3056a9); } .voy-mkTooltipInner #editbutton button:before, .voy-mkTooltipInner #infobutton button:before { content: " "; display: block; position: absolute; left: 0; top: 0; height: 100%; width: 15px; background-repeat: no-repeat; background-position: 0 25%; background-size: 12px; filter: opacity(0.45); } .voy-mkTooltipInner #editbutton button { position: relative; padding-left: 15px; } .voy-mkTooltipInner #editbutton button:before { background-image: url( "//upload.wikimedia.org/wikipedia/commons/thumb/8/8a/OOjs_UI_icon_edit-ltr.svg/120px-OOjs_UI_icon_edit-ltr.svg.png" ); } .voy-mkTooltipInner #infobutton button { position: relative; padding-left: 12px; } .voy-mkTooltipInner #infobutton button:before { left: -2px; top: -1px; background-image: url( "//upload.wikimedia.org/wikipedia/commons/thumb/0/02/Maki-information-15.svg/120px-Maki-information-15.svg.png" ); background-size: 14px; } @media screen { html.skin-theme-clientpref-night .voy-mkTooltipInner #editbutton button:before, html.skin-theme-clientpref-night .voy-mkTooltipInner #infobutton button:before { filter: invert(0.5); } } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os .voy-mkTooltipInner #editbutton button:before, html.skin-theme-clientpref-os .voy-mkTooltipInner #infobutton button:before { filter: invert(0.5); } } /* Plus code and other text styles */ .voy-mkTooltipHint { font-weight: bold; } .voy-mkTooltipPlusCode { color: #808080; } /* Styles for tooltip tail */ .voy-mkTooltipTail { background-color: transparent; width: 14px; height: 10px; position: absolute; overflow: hidden; } .voy-mkTooltipTail:before { background-color: #ffffe3; /* same colors as .voy-mkTooltipInner */ border: 1px solid #808080; box-shadow: 0 0 2px 1px rgba(0,0,0,0.5); box-sizing: border-box; position: absolute; content:""; width: 10px; height: 10px; top: 0; left: 0; } @media screen { html.skin-theme-clientpref-night .voy-mkTooltipInner, html.skin-theme-clientpref-night .voy-mkTooltipTail:before { background-color: #333; } } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os .voy-mkTooltipInner, html.skin-theme-clientpref-os .voy-mkTooltipTail:before { background-color: #333; } } /* Position-dependent styles for tooltip box */ .voy-mkBelow { padding-top: 15px; } .voy-mkAbove { padding-bottom: 15px; } .voy-mkLeft .voy-mkTooltipTail { left: 5px; } .voy-mkRight .voy-mkTooltipTail { right: 5px; } .voy-mkAbove .voy-mkTooltipTail { bottom: -10px; } .voy-mkAbove .voy-mkTooltipTail:before { transform-origin: 0 0; transform: rotate(-45deg); } .voy-mkBelow .voy-mkTooltipTail { top: -10px; } .voy-mkBelow .voy-mkTooltipTail:before { transform-origin: 0 100%; transform: rotate(45deg); } /* Marker arrow extension for mobile devices */ .voy-mkTooltipButton { border-top-right-radius: 3px; border-bottom-right-radius: 3px; padding: 0 0.15em; background-color: #fff; color: #000; cursor: pointer; font-size: 90%; } @media print { .voy-mkTooltipButton { display: none; } } /* Show complete tooltip if positioned an image container */ div.thumbinner.with-vCard, div.thumbinner.with-Marker { overflow: visible; } m3idscl4ry0bu5a3gwzyzvsdqehrfz4