WinUpGo
Αναζήτηση
CASWINO
SKYSLOTS
BRAMA
TETHERPAY
777 FREE SPINS + 300%
Καζίνο Cryptocurrency Crypto Casino Το Torrent Gear είναι η αναζήτηση όλων των χρήσεων torrent! Εργαλείο Torrent

Πώς εφαρμόζεται η πολυγλωσσία στις πλατφόρμες καζίνο

Γιατί η πολυγλωσσία των καζίνο

Οι παίκτες καταθέτουν και τοποθετούν στοιχήματα όπου κατανοούν τη διεπαφή, βλέπουν τις τιμές στο νόμισμά τους και αισθάνονται τοπική σημασία (αθλήματα, διακοπές, μέθοδοι πληρωμής, νομικά κείμενα). Η σωστή πολυγλωσσία αυξάνει registratsii→depozit CR, μειώνει την τριβή CCG/box και βελτιώνει τη διατήρηση.


Βασική ορολογία

i18n (διεθνοποίηση) - προετοιμασία του προϊόντος για εγχώρια προσαρμογή: κλειδιά, κάτοχοι θέσης, ημερομηνίες/αριθμοί/νομίσματα μορφοποίησης, υποστήριξη για RTL και κλείδες.

(Τοπική) - πραγματικές μεταφράσεις και τοπικές προσαρμογές: κείμενα, εικόνες, promo, νομικά μπλοκ, RG (υπεύθυνο παιχνίδι).

Τοπική - γλώσσα + περιφέρεια (π.χ. «pt-BR», «fr-CA»), επηρεάζει μορφότυπους, νόμισμα, νομικά πανό και περιεχόμενο.


i18n αρχιτεκτονική: πώς να ξαπλώσετε από το μηδέν

1. Κλειδιά αντί για «σκληρές» συμβολοσειρές.

Ονόματα κλειδιών κατά την έννοια ('ταμίας. κατάθεση. τίτλος ") και όχι σε όλη την οθόνη.

Γραμμές - σε μεταφραστικά αρχεία/πίνακες, όχι σε κωδικό.

2. Μορφή μηνύματος ICU.

Πληθώρα, φύλο, περιπτώσεις, νόμισμα/ημερομηνία/ποσοστό:

{καταμέτρηση, πληθυντικός, ένα {# στοίχημα} λίγα {# στοιχήματα} πολλά {# στοιχήματα} άλλα {# στοιχήματα}}

3. Μορφότυποι και νομίσματα.

Κωδικοί ISO, τοπικοί οριοθετητές, μορφότυπος ημερομηνίας «εεεε-ΜΜ-ηη» στη βάση δεδομένων, απόδοση τοπικού επιπέδου στο μπροστινό μέρος.

Μετατροπή των συναλλαγματικών ισοτιμιών στον εξυπηρετητή, απεικόνιση σύμφωνα με τους κανόνες του νομίσματος (χαρακτήρας/χώρος/θέση).

4. Timezones.

ΣΤΗ ΒΑΣΗ ΔΕΔΟΜΈΝΩΝ - UTC. Στο μπροστινό μέρος/σε γράμματα - το τοπικό TZ του παίκτη (αποθηκεύεται στο προφίλ).

5. RTL/αμφίδρομος χαρακτήρας.

Υποστήριξη 'dir = «rtl»' για 'ar', 'fa', 'he'; εικονίδια καθρέφτη, σειρά στοιχείων, στυλ κλιμάκωσης χωρίς hack.

6. Διαχωρισμός των τομέων μετάφρασης.

"core" ( ), "cashier", "kyc", "rg", "promotion ," games "," email/push "," seo ". Σας επιτρέπει να ενημερώσετε ένα μέρος χωρίς να επηρεάσετε τα πάντα.


Τι ακριβώς είναι εντοπισμένο στο καζίνο

Λόμπι/κατάλογος παιχνιδιών: ονόματα, κατηγορίες, πανό, ετικέτες αναζήτησης, περιγραφές.

Παιχνίδι και πάροχοι: όνομα/παιχνίδια, πίνακας πληρωμής/κανόνες, προειδοποιήσεις. Εάν ο πάροχος δεν παρέχει την απαιτούμενη γλώσσα, ετοιμάστε οπισθοδρόμηση και προειδοποίηση.

Ταμίας: ονομασίες μεθόδων (τοπικά APM), καταστάσεις, σφάλματα PSP, νομικά κείμενα 3-D Secure, κρύπτες on/off-ramp.

KYC/AML/RG: οδηγίες εγγράφου, χρονοδιάγραμμα/όριο κειμένων, αυτοαποκλεισμός, ηλικία και υπεύθυνα πανό.

Νομικές σελίδες: TOS, πολιτική απορρήτου, άδεια, απαγορεύσεις της χώρας, πανό μπισκότων.

Μάρκετινγκ: σελίδες προσγείωσης, promo/αποστολές/τουρνουά, ατέλειες, ηλεκτρονικό ταχυδρομείο, πανό σε CDN.

SEO meta: '', '<meta description>', 'hreflang', micro markup.</p> <hr> <h2>Ροή εργασίας</h2> <p>1. Εξαγωγή κλειδιών από το αποθετήριο (έλεγχος χιτωνίου + CI για «σκληρές» συμβολοσειρές).</p> <p>2. CAT system/TS platform (Phrase/Smartling/Lokalise κ.λπ.): λεξικό όρων, μνήμη μετάφρασης, στιγμιότυπα οθόνης πλαισίου.</p> <p>3. Ρόλοι: μεταφραστής → συντάκτης → νομική επανεξέταση (για RG/TOS/ταμειακό γραφείο).</p> <p>4. QA τοπικών: οπισθοδρόμηση UI (στιγμιότυπα οθόνης), αυτοτεστίες για πληθυντικούς και ICU, έλεγχος του μήκους των γραμμών/κατακερματισμών.</p> <p>5. Έκδοση: «lang pack» ως τεχνούργημα, συμβατότητα με προηγούμενη σύμβαση. canary rollout% σε 5-10 τοπικό κοινό.</p> <p>6. Παράδοση: Δηλωτικά CDN + εκκαθάριση ετικετών (γρήγορη δημοσίευση χωρίς έκδοση υποστήριξης).</p> <hr> <h2>Τοπική στρατηγική</h2> <p>Ελάχιστο σύνολο: ΕΝ + βασικές αγορές (π.χ. «es-E ,» pt-BR «,» tr-TR «,» de-DE «,» fr-FR «,» pl-PL «,» ru-RU «,» UK-UA «,» ar-AE «,» ms-MY «,» th-T«, »ja JP ').</p> <p>Γλωσσικές επιλογές: «es-ES» ≠ «es-MX» (όροι box office, αθλητισμός, νομικές διατυπώσεις).</p> <p>Σκάλα: «fr-CA-fr-en». Ο παίκτης βλέπει πάντα έγκυρο κείμενο.</p> <p>Geo απόδοση και επιλογή παικτών: αυτόματη πρόταση τοπικού από IP/browser + σαφής διακόπτης στην κεφαλίδα και το προφίλ.</p> <hr> <h2>Συμμόρφωση και νομικές απαιτήσεις</h2> <p>Τα πανό ηλικίας/ευθύνης αντιστοιχούν στη δικαιοδοσία: διατύπωση, οργανώσεις επαφής, σύνδεσμοι.</p> <p>KYC/AML/KYT: ακριβείς όροι, σαφείς οδηγίες (μορφή εγγράφων, μεταφραστής δεν αντικαθιστά!).</p> <p>Όροι προώθησης: νομικοί όροι promo σε κάθε τόπο (όχι αυτόματη μετάφραση!).</p> <p>Γεωγραφική οριοθέτηση των κειμένων: στις απαγορευμένες χώρες - οι αντίστοιχες κοινοποιήσεις/δέσμες και όχι 404 στα αγγλικά.</p> <hr> <h2>UX μέρη που συνήθως «σπάνε»</h2> <p>Πληθώρα και αριθμοί (οι σλαβικές γλώσσες έχουν 3-4 μορφές).</p> <p>Μακριές λέξεις/ταπετσαρία (γερμανικά/φινλανδικά) - ευέλικτο πλέγμα, «παύλα: αυτόματο».</p> <p>RTL και εικονίδια - βέλη κατόπτρων/ακίδες, ευθυγράμμιση ποσοτήτων.</p> <p>Μορφότυποι χρήματος: χώροι/διαχωριστές, θέση χαρακτήρων, στρογγυλοποίηση, «λεπτοί χώροι» για χιλιάδες.</p> <p>Σφάλματα στο box office - απαγόρευση του «σκληρού» αγγλικού κειμένου από το PSP. Χαρτογράφηση κωδικών → τοπικά μηνύματα</p> <hr> <h2>SEO και επιδόσεις</h2> <p>Δομή URL: υποδιευθυντές ('/de/', '/fr/'), όχι υποδιαιρέσεις (ευκολότερη διαχείριση cookies/locale).</p> <p>«hreflang» και κανονικό μεταξύ των τόπων, τοπικό sitemap.</p> <p>CDN cache of the JSON lobby by locale with 'stale-while-revalidate'.</p> <p>Εικόνες/πανό - τοπικές επιγραφές/νομίσματα. αυτόματη μετατροπή μορφοτύπου (WebP/AVIF).</p> <p>Μεταφραστικά πακέτα - δυναμική εισαγωγή ανά τόπο, μην σύρετε όλες τις γλώσσες ταυτόχρονα.</p> <hr> <h2>Πάροχοι παιχνιδιών και εντοπισμός</h2> <p>Πίνακας υποστηριζόμενων γλωσσών για κάθε πάροχο/παιχνίδι; επιστροφή σε γλώσσα λόμπι ή «Αγγλικά με αποποίηση ευθύνης».</p> <p>Πίνακας πληρωμής/Βοήθεια: αν το κείμενο είναι κλειστό, ένας ξεχωριστός οδηγός επικάλυψης του τόπου σας.</p> <p>Γεγονότα και σφάλματα από τον πάροχο - ομαλοποίηση και τοπική mappa.</p> <hr> <h2>Τηλεμετρία και A/B</h2> <p>Μετρήσεις τόπου: CR 'register→KYC→deposit', 'deposit→bet', NPS, churn, ταχύτητα KYC, αποτυχία box office.</p> <p>Δοκιμές διατύπωσης: τα τοπικά ταμειακά/promo κείμενα συχνά δίνουν + X% στη μετατροπή.</p> <p>Ανίχνευση «σπασμένων» μεταφράσεων: η αύξηση των κλικ στο «Help», άτυπα μακρές ώρες παραμονής στο ταμειακό μητρώο.</p> <hr> <h2>Αντι-μοτίβα</h2> <p>Σκληρές γραμμές στον κώδικα και ανάμειξη γλώσσας/λογικής.</p> <p>Έλλειψη ICU → «2 στοίχημα «/» 5 στοίχημα »αντί για ορθές μορφές.</p> <p>Αυτόματη μετάφραση νομικών κειμένων/ταμειακών γραφείων/πληρωμών.</p> <p>Μία γλώσσα για όλες τις χώρες (π.χ. «es-ES» στο LATAM) - πολιτιστικά και ορολογικά σφάλματα.</p> <p>Παγκόσμια διαφημιστικά πανό χωρίς τοπικούς όρους → αξιώσεις της ρυθμιστικής αρχής/των παικτών.</p> <p>Καμία οπισθοδρόμηση → κενές γραμμές/αγγλικό κείμενο «ψάρι».</p> <p>Το πακέτο όλων των γλωσσών σε κάθε σελίδα → υπέρβαρο και αργό TTFB.</p> <hr> <h2>Πολύγλωσση λίστα ελέγχου Καζίνο</h2><p>Αρχιτεκτονική και δεδομένα</p> <ul style="padding-left:0; list-style:none; margin:10px 0 14px;"> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>i18n πλήκτρα, μορφότυποι ICU, UTC στη βάση δεδομένων, TZ στο μπροστινό μέρος/με γράμματα.</li> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Νομίσματα/μορφότυποι/οριοθετητές είναι από τον τόπο, όχι «χειροκίνητοι» κανόνες.</li> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Υποστήριξη RTL, αντικατοπτρισμός εικονιδίων, αυτοεννόηση.</li> </ul> <h2>Περιεχόμενο και ροή εργασίας</h2> <ul style="padding-left:0; list-style:none; margin:10px 0 14px;"> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>πλατφόρμα CAT, γλωσσάριο όρων, πρόσβαση σε στιγμιότυπα οθόνης πλαισίου.</li> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Ρόλοι: perevod→redaktura→yuridichesky αναθεώρηση.</li> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Canary publication 'lang pack', CDN delivery and tag-purge.</li> </ul> <h2>Πεδία</h2> <ul style="padding-left:0; list-style:none; margin:10px 0 14px;"> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Λόμπι/παιχνίδια/box office/KYC/RG/legal/marketing/SEO - καλύπτονται και διαχωρίζονται.</li> </ul> <p>Χαρτογράφηση σφαλμάτων PSP/ISP σε τοπικά μηνύματα.</p> <ul style="padding-left:0; list-style:none; margin:10px 0 14px;"> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Μήτρα γλώσσας ανά πάροχο παιχνιδιού (οπισθοδρόμηση + επικάλυψη).</li> </ul> <h2>SEO/Perf</h2> <ul style="padding-left:0; list-style:none; margin:10px 0 14px;"> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>'/locale/' URL, 'hreflang', τοπικό sitemap.</li> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Δυναμική εισαγωγή μεταφράσεων, JSON lobby cache.</li> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Βελτιστοποίηση εικόνας/βίντεο CDN για τοπική χρήση.</li> </ul> <h2>Συμμόρφωση</h2> <ul style="padding-left:0; list-style:none; margin:10px 0 14px;"> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Τα νομικά κείμενα και τα κείμενα RG ελέγχονται τοπικά.</li> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Γεωγραφική περίφραξη και απαγορευτικά/ηλικιακά κείμενα.</li> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Cookie/συγκατάθεση στη γλώσσα του χρήστη.</li> </ul> <h2>Παρατηρησιμότητα</h2> <ul style="padding-left:0; list-style:none; margin:10px 0 14px;"> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Μετρήσεις CR/αστοχίας/Latency ανά τόπο.</li> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>Προειδοποιήσεις για «σπασμένα» κλειδιά και κενές γραμμές.</li> <li><span style="display:inline-flex; width:18px; height:18px; margin-right:8px; align-items:center; justify-content:center; flex:0 0 18px;;color:#c0cc4c"><svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="currentColor"/><path d="M16.5 9.5l-5.1 5.1L7.5 10.7" fill="none" stroke="#000" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>A/B σχετικά με την κρίσιμη διατύπωση (ταμειακή υπηρεσία/CCM/promo).</li> </ul> <hr> <p>Η πολυγλωσσία στο iGaming δεν "μεταφράζει μερικές γραμμές. "Αυτή είναι μια πειθαρχία συστήματος: i18n αρχιτεκτονική, μορφότυποι ICU, αυστηρή ροή εργασίας μετάφρασης, συμμόρφωση, παράδοση CDN και παρατηρησιμότητα. Καθιστώντας το μέρος της πλατφόρμας, θα αυξήσετε τη μετατροπή, θα μειώσετε την τριβή στο checkout και θα περάσετε τις νομικές απαιτήσεις χωρίς «χειροκίνητες» πυρκαγιές - ενώ θα κλιμακώνετε το περιεχόμενο και τις αγορές προβλέψιμα και γρήγορα.</p></div> <style> /* ===== Общая типографика ===== */ .geo-grid,.countries{ font-family: Segoe UI,system-ui,-apple-system,Roboto,Arial,sans-serif; } /* ========================================= L1 — ОСНОВНЫЕ РАЗДЕЛЫ (вертикальный список) ========================================= */ .geo-grid{ /* Был grid-карточек — делаем строго вертикальный список */ display: flex; flex-direction: column; gap: 0; /* без зазоров — как чистый список */ margin: 0; padding: 0; } /* Перестилизуем .geo-card под «элемент списка» */ .geo-card{ display: block; text-decoration: none; color: #eaf0ff; background: transparent; border: 0; border-left: 3px solid transparent; /* тонкий левый акцент по hover */ border-radius: 0; padding: 12px 10px 12px 14px; transition: background .12s ease, border-color .12s ease, transform .06s ease; } /* Межстрочные разделители */ .geo-card + .geo-card{ border-top: 1px solid rgba(148,163,184,.10); } /* Содержимое — компактно в колонку */ .geo-card__body{ display: flex; flex-direction: column; gap: 4px; min-width: 0; } /* Заголовок раздела — акцент */ .geo-card__title{ margin: 0; font-weight: 800; font-size: 17px; line-height: 1.2; color: #ffffff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* Короткое описание — в одну строку */ .geo-card__desc{ margin: 0; font-size: 13px; line-height: 1.35; color: #b8c4d9; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; /* вики-стиль: только одна строка */ overflow: hidden; } /* CTA превращаем в маленький чип-ярлык справа налево */ .geo-card__cta{ align-self: flex-start; margin-top: 2px; font-size: 12px; font-weight: 700; letter-spacing: .2px; color: #2a1b00; background: linear-gradient(180deg,#fff27a,#ffe85c 55%,#ffc933); border: 1px solid #e3b600; border-radius: 8px; padding: 4px 8px; box-shadow: 0 1px 0 rgba(0,0,0,.06) inset; } /* Hover — мягкий подсвет и левый акцент */ .geo-card:hover{ background: linear-gradient(180deg, rgba(255,255,255,.03), rgba(255,255,255,.01)); border-left-color: #ffe85c; } .geo-card:active{ transform: translateY(1px); } /* ========================================= L2 — СТАТЬИ (вертикальный список «каталог») ========================================= */ .countries-wrap{ margin-top: 16px; padding: 8px 10px; border: 1px solid rgba(148,163,184,.10); border-radius: 10px; background: linear-gradient(180deg, rgba(255,255,255,.015), rgba(255,255,255,.008)); } /* Список одной колонкой, без точек */ .countries{ list-style: none; margin: 0; padding: 0; display: block; } /* Элемент списка статьи */ .country-li{ margin: 0; } /* Сама ссылка — компактная строка с разделителем */ .country-link{ position: relative; display: grid; grid-template-columns: 1fr 18px; /* название | стрелка */ align-items: center; column-gap: 10px; padding: 9px 2px; text-decoration: none; color: #dfe7ff; transition: background .12s ease, color .12s ease, transform .06s ease; } /* Тонкий разделитель между строками */ .country-link + .country-link{ border-top: 1px dashed rgba(148,163,184,.15); } /* Название статьи */ .country-name{ font-weight: 600; letter-spacing: .2px; color: #eef3ff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 14px; } /* Стрелка справа */ .country-arrow{ display: flex; align-items: center; justify-content: center; color: rgba(255,255,255,.28); transition: color .12s ease, transform .12s ease; } /* Hover/Focus */ .country-link:hover{ color: #ffffff; background: rgba(255,255,255,.02); } .country-link:hover .country-arrow{ color: #ffe85c; transform: translateX(2px); } .country-link:active{ transform: translateY(1px); } .country-link:focus-visible{ outline: 2px solid #93c5fd; outline-offset: 2px; } /* ===== Адаптив ===== */ @media (max-width: 680px){ .geo-card{ padding: 10px 8px 10px 12px; } .geo-card__title{ font-size: 16px; } .geo-card__desc{ -webkit-line-clamp: 2; } /* на мобиле можно две строки */ .countries-wrap{ padding: 6px 8px; } } </style> </div> </div> </main> <footer> <div style="display: flex; justify-content: space-between; align-items:center; padding-top:20px;"> <div style="padding-left:5px;"> <div class="language-selector"> <button class="language-button"> <span style="display: inline-flex; align-items: center;"> <svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right: 10px;"> <path fill-rule="evenodd" clip-rule="evenodd" d="M9.52 4.392A8.009 8.009 0 0 0 4.061 11h2.997c.227-2.363 1.078-4.627 2.46-6.608Zm4.96 0c1.383 1.981 2.234 4.245 2.461 6.608h2.997a8.009 8.009 0 0 0-5.457-6.608ZM14.93 11c-.269-2.373-1.28-4.642-2.93-6.54C10.35 6.357 9.339 8.626 9.07 11h5.86Zm-5.86 2h5.86c-.269 2.373-1.28 4.642-2.93 6.54-1.65-1.898-2.661-4.167-2.93-6.54Zm-2.011 0H4.062a8.009 8.009 0 0 0 5.457 6.608C8.137 17.627 7.286 15.363 7.06 13Zm7.422 6.608c1.382-1.981 2.233-4.245 2.46-6.608h2.997a8.008 8.008 0 0 1-5.457 6.608ZM2 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10S2 17.523 2 12Z" fill="#fff"></path> </svg> Ελληνικά </span> </button> <div class="language-menu"> <a hreflang="en" href="https://winupgo.com/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">English</a><a hreflang="es" href="https://winupgo.com/es/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Español</a><a hreflang="fr" href="https://winupgo.com/fr/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Français</a><a hreflang="pt" href="https://winupgo.com/pt/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Português</a><a hreflang="ru" href="https://winupgo.com/ru/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Русский</a><a hreflang="zh-Hans" href="https://winupgo.com/cn/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">简体中文</a><a hreflang="zh-Hant" href="https://winupgo.com/tw/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">繁體中文</a><a hreflang="ja" href="https://winupgo.com/jp/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">日本語</a><a hreflang="ko" href="https://winupgo.com/kr/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">한국어</a><a hreflang="hi" href="https://winupgo.com/hi/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">हिन्दी</a><a hreflang="fa" href="https://winupgo.com/fa/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">فارسی</a><a hreflang="ar" href="https://winupgo.com/ar/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">العربية</a><a hreflang="tr" href="https://winupgo.com/tr/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Türkçe</a><a hreflang="uz" href="https://winupgo.com/uz/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Oʻzbekcha</a><a hreflang="kk" href="https://winupgo.com/kz/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">қазақ</a><a hreflang="tk" href="https://winupgo.com/tk/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Türkmençe</a><a hreflang="ky" href="https://winupgo.com/ky/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Кыргызча</a><a hreflang="tg" href="https://winupgo.com/tg/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Тоҷикӣ</a><a hreflang="ka" href="https://winupgo.com/ka/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">ქართული</a><a hreflang="he" href="https://winupgo.com/he/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">עברית</a><a hreflang="az" href="https://winupgo.com/az/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Azərbaycan dili</a><a hreflang="hy" href="https://winupgo.com/hy/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Հայերեն</a><a hreflang="de" href="https://winupgo.com/de/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Deutsch</a><a hreflang="it" href="https://winupgo.com/it/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Italiano</a><a hreflang="pl" href="https://winupgo.com/pl/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Polski</a><a hreflang="ro" href="https://winupgo.com/ro/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Română</a><a hreflang="el" href="https://winupgo.com/el/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Ελληνικά</a><a hreflang="uk" href="https://winupgo.com/ua/wiki/casino-technology/how-multilingualism-is-implemented-on-casino-platforms/">Українська</a> </div> </div> </div> <div class="copy" style="flex: 1;text-align:right;padding-right:10px;"> © <b>Win<u>Up</u>Go</b> 2024 </div> <div style="width:70;padding-right:5px;"> <div style="display:flex;gap:10px;justify-content:flex-end;"> <a target="_blank" rel="noopener noreferrer nofollow sponsored" href="https://t.me/winupgo"><img width="30" height="30" alt="WinUpGo Channel" src="https://winupgo.com/images/telegram.svg"></a> <a href="/el/feedback-form/"><img width="30" height="30" alt="Έντυπο ανάδρασης" src="https://winupgo.com/images/feedback.svg"></a> </div> </div> </div> </footer> </div> <script src="/js/jquery-3.6.0.min.js"></script> <script> function MyLoc(url) { document.location.href = url; } document.addEventListener('DOMContentLoaded', () => { const button = document.querySelector('.language-button'); const menu = document.querySelector('.language-menu'); const languageSelector = document.querySelector('.language-selector'); button.addEventListener('click', (e) => { e.stopPropagation(); // Предотвращение всплытия события menu.classList.toggle('show'); }); document.addEventListener('click', (e) => { // Проверка, был ли клик вне области кнопки и меню if (!languageSelector.contains(e.target)) { menu.classList.remove('show'); } }); }); //alert("Ширина экрана: " + window.innerWidth + " пикселей"); </script> <script> $(document).ready(function() { $('#changpwd').click(function(){ //$('#err').text(''); var hashkey = $('#hashkey').val(); var pass = $('#pass').val(); var pass2 = $('#pass2').val(); if(pass != pass2 || pass == ""){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Ο κωδικός δεν ταιριάζει ή είναι κενός", 'error'); exit; } $.ajax({ url: "/ajax.php", // куда отправляем type: "post", // метод передачи dataType: "json", // тип передачи данных data: { // что отправляем "action": "changpwd", "hashkey": hashkey, "pass": pass }, // после получения ответа сервера success: function(data){ //alert('yes'); if(data.result == "success"){ $('#main_fr').html("<div class=\"success\">Ο κωδικός άλλαξε επιτυχώς! <a href='/private/' class='const_link'>Είσοδος</a></div>"); showNotification("<img src=\"https://winupgo.com/images/msg-success.svg\" width=\"30\" height=\"30\" alt=\"Success\">Ο κωδικός άλλαξε", 'success'); window.scrollTo({top: 0, behavior: 'smooth'}); exit; }else{ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Παρουσιάστηκε σφάλμα συστήματος, επικοινωνήστε με την υποστήριξη.", 'error'); exit; } } }); }); $('#respassword').click(function(){ //$('#err').text(''); var email = $('#email').val(); if(email == ""){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Εισάγετε email", 'error'); exit; } if(!email.includes('@') || !email.includes('.')){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Μη έγκυρη μορφή email", 'error'); exit; } $.ajax({ url: "/ajax.php", // куда отправляем type: "post", // метод передачи dataType: "json", // тип передачи данных data: { // что отправляем "action": "respassword", "email": email }, // после получения ответа сервера success: function(data){ //alert('yes'); if(data.result == "success"){ $('#main_fr').html("<div class=\"success\">Οι οδηγίες για ανάκτηση κωδικού στάλθηκαν στο email σας. Αν δεν λάβατε το μήνυμα, ελέγξτε τον φάκελο SPAM.</div>"); showNotification("<img src=\"https://winupgo.com/images/msg-success.svg\" width=\"30\" height=\"30\" alt=\"Success\">Οι οδηγίες στάλθηκαν", 'success'); //window.scrollTo({top: 0, behavior: 'smooth'}); exit; }else{ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Παρουσιάστηκε σφάλμα συστήματος, επικοινωνήστε με την υποστήριξη.", 'error'); exit; } } }); }); $('#edit').click(function(){ var nickname = $('#nickname').val(); var pass = $('#pass').val(); var pass2 = $('#pass2').val(); if(nickname == ""){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Εισάγετε ψευδώνυμο", 'error'); exit; } /*if(pass != pass2 || pass == ""){ showNotification('Ο κωδικός δεν ταιριάζει ή είναι κενός', 'error'); exit; }*/ $.ajax({ url: "/ajax.php", // куда отправляем type: "post", // метод передачи dataType: "json", // тип передачи данных data: { // что отправляем "action": "edit", "nickname": nickname }, // после получения ответа сервера success: function(data){ //alert('yes'); if(data.result == "success"){ showNotification("<img src=\"https://winupgo.com/images/msg-success.svg\" width=\"30\" height=\"30\" alt=\"Success\">Το προφίλ ενημερώθηκε", 'success'); //window.scrollTo({top: 0, behavior: 'smooth'}); exit; }else{ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Το ψευδώνυμο χρησιμοποιείται ήδη", 'error'); exit; } } }); }); $('#log').click(function(){ //$('#err').text(''); //alert('ok'); var email = $('#email').val(); var pass = $('#pass').val(); if(email == ""){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Εισάγετε email", 'error'); exit; } if(pass == ""){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Σφάλμα σύνδεσης", 'error'); exit; } $.ajax({ url: "/ajax.php", // куда отправляем type: "post", // метод передачи dataType: "json", // тип передачи данных data: { // что отправляем "action": "login", "email": email, "pass": pass }, // после получения ответа сервера success: function(data){ if(data.result == "error"){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Σφάλμα σύνδεσης", 'error'); exit; }else{ document.location.href = "/el/private/"; exit; } } }); }); $('#reg').click(function(){ var email = $('#email').val(); var pass = $('#pass').val(); var pass2 = $('#pass2').val(); if(email == ""){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Εισάγετε email", 'error'); exit; } if(!email.includes('@') || !email.includes('.')){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Μη έγκυρη μορφή email", 'error'); exit; } if(pass != pass2 || pass == ""){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Ο κωδικός δεν ταιριάζει ή είναι κενός", 'error'); exit; } $.ajax({ url: "/ajax.php", // куда отправляем type: "post", // метод передачи dataType: "json", // тип передачи данных data: { // что отправляем "action": "registration", "email": email, "pass": pass }, // после получения ответа сервера success: function(data){ //alert('yes'); if(data.result == "success"){ $('#main_fr').html("<div class=\"success\">Η εγγραφή ολοκληρώθηκε με επιτυχία! Επιβεβαιώστε το email σας, αν δεν λάβατε το μήνυμα, ελέγξτε τον φάκελο SPAM. <a href='/private/' class='const_link'>Είσοδος</a></div>"); showNotification("<img src=\"https://winupgo.com/images/msg-success.svg\" width=\"30\" height=\"30\" alt=\"Success\">Επιτυχής εγγραφή", 'success'); window.scrollTo({top: 0, behavior: 'smooth'}); exit; }else{ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Ο χρήστης είναι ήδη εγγεγραμμένος", 'error'); exit; } } }); }); $('#sendmessage').click(function(){ var email = $('#email').val(); var message = $('#message').val(); var token = $('#form_token').val(); if(email === ""){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Εισάγετε email", 'error'); return; // <-- было 'exit' } if(!email.includes('@') || !email.includes('.')){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Μη έγκυρη μορφή email", 'error'); return; } if(message === ""){ showNotification("<img src=\"https://winupgo.com/images/msg-error.svg\" width=\"30\" height=\"30\" alt=\"Error\">Εισάγετε κείμενο μηνύματος", 'error'); return; } $.ajax({ url: "/ajax.php", type: "POST", dataType: "json", data: { action:'sendmessage', email: email, message: message, form_token: token }, success: function(data){ if(data.status === "success"){ $('#email').val(''); $('#message').val(''); //$('#main_fr').html("<div class=\"success\">Ευχαριστούμε για την επικοινωνία.</div>"); showNotification("<img src=\"https://winupgo.com/images/msg-success.svg\" width=\"30\" height=\"30\" alt=\"Success\">Το μήνυμα στάλθηκε", 'success'); //window.scrollTo({top: 0, behavior: 'smooth'}); } else { // покажем сообщение сервера, если есть showNotification(data.message || "Εκτελούνται τεχνικές εργασίες", 'error'); } }, error: function(){ showNotification("Εκτελούνται τεχνικές εργασίες", 'error'); } }); }); }); function Work(){ showNotification("<img src=\"https://winupgo.com/images/msg-warning.svg\" width=\"30\" height=\"30\" alt=\"Warning\">Εκτελούνται τεχνικές εργασίες", 'warning'); } </script> <style> /* Контейнер чекбокса */ .chk-wrap { margin: 0 0 16px; } /* увеличенный отступ снизу */ .chk { display:block; /* кликабельна вся строка */ padding:10px 12px; /* комфортная хит-зона */ border-radius:10px; cursor:pointer; user-select:none; transition: background .18s ease, box-shadow .18s ease; } .chk:hover { background: rgba(255,255,255,.06); } .chk:active { background: rgba(255,255,255,.10); } /* Внутренности */ .chk-inner { display:flex; align-items:center; gap:10px; } .chk-input { position:absolute; opacity:0; width:1px; height:1px; pointer-events:none; } .chk-box { position:relative; width:18px; height:18px; border:1.6px solid rgba(255,255,255,.85); border-radius:5px; background:transparent; transition: border-color .18s ease, background-color .18s ease; flex:0 0 auto; } .chk-box::after { content:""; position:absolute; left:5px; top:2.5px; width:6px; height:10px; border-right:2.5px solid transparent; border-bottom:2.5px solid transparent; transform: rotate(45deg); transition: border-color .14s ease; } /* Checked */ .chk-input:checked + .chk-box { background:#fff; border-color:#fff; } .chk-input:checked + .chk-box::after { border-right-color:#0b0f1a; border-bottom-color:#0b0f1a; } /* Фокус с клавиатуры на весь блок */ .chk-input:focus-visible ~ .chk-label, .chk-input:focus-visible + .chk-box { box-shadow: 0 0 0 3px rgba(255,255,255,.18); outline: 2px solid #ffffff; outline-offset: 2px; } .chk-label { color:#eaeff7; font:600 14px/1.2 Segoe UI, system-ui; opacity:.95; } </style> <!-- Разметка --> <div id="searchModal" class="search-modal"> <div class="search-modal-content"> <span class="search-close-button">×</span> <span class="h1">Αναζήτηση παιχνιδιών</span> <!-- Поле ввода --> <div style="margin:8px 0 6px;"> <input type="text" id="searchInput" class="search-input" placeholder="Εισάγετε το όνομα του παιχνιδιού" style="width:100%; display:block;"> </div> <!-- Чекбокс под полем (вся строка кликабельна) --> <div class="chk-wrap"> <label class="chk" for="onlyDemo"> <span class="chk-inner"> <input type="checkbox" id="onlyDemo" class="chk-input" /> <span class="chk-box" aria-hidden="true"></span> <span class="chk-label">Μόνο demo</span> </span> </label> </div> <div id="searchResults" class="search-results"> <div style="padding:24px 12px; text-align:center; color:#c7cfe0; font:600 14px/1.4 Segoe UI,system-ui;"> Εισαγάγετε τουλάχιστον 3 χαρακτήρες για να ξεκινήσει η αναζήτηση. </div> </div> </div> </div> <script> // helpers function openSearchModal() { const m = document.getElementById("searchModal"); m.style.display = "flex"; document.getElementById("searchInput").focus(); document.body.style.overflow = 'hidden'; } function resetSearchForm() { const input = document.getElementById("searchInput"); const cb = document.getElementById("onlyDemo"); const res = document.getElementById("searchResults"); input.value = ""; cb.checked = false; res.innerHTML = ""; } function closeSearchModal() { document.getElementById("searchModal").style.display = "none"; document.body.style.overflow = ''; resetSearchForm(); } // Открытие модального окна document.getElementById("searchButton").onclick = openSearchModal; // Закрытие модального окна (крестик) document.querySelector(".search-close-button").onclick = closeSearchModal; // Закрытие при клике вне модального окна window.addEventListener("click", function(event) { const searchModal = document.getElementById("searchModal"); if (event.target === searchModal) closeSearchModal(); }); // Закрытие по ESC window.addEventListener("keydown", function(e){ if (e.key === "Escape") { const searchModal = document.getElementById("searchModal"); if (searchModal.style.display === "flex") closeSearchModal(); } }); // Хелпер: выполнение запроса function doSearch(query, page) { const demo = document.getElementById('onlyDemo').checked ? 1 : 0; const url = "/search.php?lang=/el" + (page ? "&page=" + encodeURIComponent(page) : "") + "&query=" + encodeURIComponent(query) + "&demo=" + demo; const xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { document.getElementById("searchResults").innerHTML = xhr.responseText; } }; xhr.send(); } // Отправка запроса при вводе текста document.getElementById("searchInput").addEventListener("input", function() { const query = this.value.trim(); if (query.length > 2) { doSearch(query, 1); } else { document.getElementById("searchResults").innerHTML = "<div style=\"padding:24px 12px; text-align:center; color:#c7cfe0; font:600 14px/1.4 Segoe UI,system-ui;\">Εισαγάγετε τουλάχιστον 3 χαρακτήρες για να ξεκινήσει η αναζήτηση.</div>"; } }); // Триггерить поиск и по клику на чекбокс (если текста уже >=3) document.getElementById('onlyDemo').addEventListener('change', function() { const query = document.getElementById('searchInput').value.trim(); if (query.length > 2) doSearch(query, 1); }); // Пагинация function paginSearch(page){ const query = document.getElementById("searchInput").value.trim(); doSearch(query, page); if (window.$) { $('#searchResults').animate({ scrollTop: 0 }, 500); } else { document.getElementById('searchResults').scrollTo({ top: 0, behavior: 'smooth' }); } } </script> <!-- HTML для уведомления --> <div id="notification" class="notification"></div> <!-- Скрипт для управления уведомлением --> <script> function showNotification(message, type) { var notification = document.getElementById('notification'); // Сначала показываем уведомление notification.innerHTML = message; notification.classList.add(type); notification.classList.add('show'); // Убираем уведомление через 3 секунды setTimeout(function() { // Начинаем скрывать уведомление notification.classList.remove('show'); // После завершения анимации скрытия удаляем классы и готовим к следующему показу setTimeout(function() { notification.classList.remove(type); notification.innerHTML = ''; }, 300); // длительность анимации скрытия (равна времени transition) }, 3000); // убрать уведомление через 3 секунды } </script> <script> (function(){ var _fbIO = null; function initFloatingBanner(){ if (window.__fbInitOnce) return; // защита от повторной инициализации window.__fbInitOnce = true; var topBanner = document.getElementById('top-banner'); var floatingBanner = document.getElementById('floating-banner'); var closeBtn = document.getElementById('close-floating-banner'); var HIDE_KEY = 'floatingBannerHiddenUntil'; // ручное закрытие (кнопка) var HIDE_DURATION = 300 * 1000; // 300 сек var HIDE_TMP_KEY = 'floatingBannerHiddenTempUntil'; // закрытие вне/ESC/диммер var HIDE_TMP_MS = 30 * 1000; // 30 сек var TRANS_MS = 300; // длительность CSS-перехода var SHOW_DELAY_MS = 4 * 1000; // задержка показа 4 сек if (!floatingBanner) return; // === Диммер страницы === var dim = document.getElementById('floating-dim'); if (!dim) { dim = document.createElement('div'); dim.id = 'floating-dim'; dim.setAttribute('style', 'position:fixed;inset:0;'+ 'background:rgba(0,0,0,.45);opacity:0;'+ 'pointer-events:none;transition:opacity .15s ease;'+ 'z-index:1000;' ); document.body.appendChild(dim); } if (!floatingBanner.style.zIndex) floatingBanner.style.zIndex = '1001'; function showDim(){ dim.style.opacity = '1'; dim.style.pointerEvents = 'auto'; } function hideDim(){ dim.style.opacity = '0'; dim.style.pointerEvents = 'none'; } // Клик по диммеру = закрытие на HIDE_TMP_MS dim.addEventListener('click', function(){ setHideFor(HIDE_TMP_MS); wantHide(); }); function setHideFor(ms){ // universal setter: скрыть до now+ms var until = Date.now() + Math.max(0, ms|0); if (ms >= HIDE_DURATION) { localStorage.setItem(HIDE_KEY, String(until)); } else { localStorage.setItem(HIDE_TMP_KEY, String(until)); } } function canShowBanner() { var hiddenUntil = parseInt(localStorage.getItem(HIDE_KEY) || '0', 10); var hiddenTempUntil = parseInt(localStorage.getItem(HIDE_TMP_KEY) || '0', 10); var until = Math.max(hiddenUntil, hiddenTempUntil); return Date.now() > until; } function isVisible(){ return floatingBanner.classList.contains('is-visible') && getComputedStyle(floatingBanner).display !== 'none' && !floatingBanner.hasAttribute('aria-hidden'); } var busy = false; var debounceTimer = null; var showTimer = null; function clearShowTimer(){ if (showTimer) { clearTimeout(showTimer); showTimer = null; } } function setVisible(next) { if (busy) return; var current = isVisible(); if (next === current) return; busy = true; if (next) { // SHOW floatingBanner.style.display = 'block'; floatingBanner.style.pointerEvents = ''; floatingBanner.removeAttribute('aria-hidden'); floatingBanner.removeAttribute('inert'); void floatingBanner.offsetWidth; // форс-рефлоу floatingBanner.classList.add('is-visible'); showDim(); var onEndShow = function(){ floatingBanner.removeEventListener('transitionend', onEndShow); busy = false; }; floatingBanner.addEventListener('transitionend', onEndShow, { once:true }); setTimeout(function(){ floatingBanner.removeEventListener('transitionend', onEndShow); busy = false; }, TRANS_MS + 50); } else { // HIDE floatingBanner.classList.remove('is-visible'); floatingBanner.style.pointerEvents = 'none'; floatingBanner.setAttribute('aria-hidden','true'); floatingBanner.setAttribute('inert',''); var onEndHide = function(){ floatingBanner.removeEventListener('transitionend', onEndHide); floatingBanner.style.display = 'none'; hideDim(); busy = false; }; floatingBanner.addEventListener('transitionend', onEndHide, { once:true }); setTimeout(function(){ floatingBanner.removeEventListener('transitionend', onEndHide); floatingBanner.style.display = 'none'; hideDim(); busy = false; }, TRANS_MS + 80); } } function eligibleNow(){ // можно показывать и верхний баннер вне экрана if (!canShowBanner()) return false; if (!topBanner) return true; var rect = topBanner.getBoundingClientRect(); return rect.bottom <= 0; } function wantShow() { // планируем показ с задержкой clearTimeout(debounceTimer); clearShowTimer(); if (!canShowBanner()) return; showTimer = setTimeout(function(){ showTimer = null; if (eligibleNow()) setVisible(true); }, SHOW_DELAY_MS); } function wantHide() { clearTimeout(debounceTimer); clearShowTimer(); debounceTimer = setTimeout(function(){ setVisible(false); }, 120); } // Кнопка закрытия — скрываем на 300 сек if (closeBtn) { closeBtn.onclick = function (e) { e.preventDefault(); e.stopPropagation(); setHideFor(HIDE_DURATION); wantHide(); }; } // Закрытие при клике вне баннера и по Esc — на 60 сек (function initOutsideClose(){ if (window.__fbOutsideCloseInit) return; window.__fbOutsideCloseInit = true; function hideTemp(){ setHideFor(HIDE_TMP_MS); wantHide(); } function onDocPointer(e){ if (!isVisible()) return; if (!floatingBanner.contains(e.target)) hideTemp(); } document.addEventListener('mousedown', onDocPointer, true); document.addEventListener('touchstart', onDocPointer, {passive:true, capture:true}); document.addEventListener('keydown', function(e){ if (e.key === 'Escape' && isVisible()) hideTemp(); }); })(); // Если нет верхнего баннера — показываем с задержкой, когда можно if (!topBanner) { if (canShowBanner()) wantShow(); return; } // Обсервер верхнего баннера if (_fbIO) { try { _fbIO.disconnect(); } catch(e){} _fbIO = null; } _fbIO = new IntersectionObserver(function (entries) { var entry = entries[0]; if (entry.isIntersecting) { // верхний виден -> скрыть и отменить отложенный показ wantHide(); } else { // верхний ушёл -> планируем показ с задержкой if (canShowBanner()) wantShow(); } }, { root: null, rootMargin: '0px 0px -10% 0px', threshold: 0 }); _fbIO.observe(topBanner); // Стартовое состояние (учитываем задержку) (function(){ var rect = topBanner.getBoundingClientRect(); if (rect.bottom <= 0) { if (canShowBanner()) wantShow(); } else { setVisible(false); } })(); // Ресайз/поворот window.addEventListener('resize', function(){ clearTimeout(debounceTimer); debounceTimer = setTimeout(function(){ var rect = topBanner.getBoundingClientRect(); if (rect.bottom <= 0) { if (canShowBanner()) wantShow(); } else { wantHide(); } }, 120); }, { passive:true }); } document.addEventListener('DOMContentLoaded', initFloatingBanner); window.addEventListener('pageshow', initFloatingBanner); // BFCache })(); </script> <script> // Функция для учета кликов function trackClick(num) { fetch('/ajax-banner.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'click', num: num }) }).catch(console.error); } // Функция для учета показов function trackView(num) { fetch('/ajax-banner.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'show', num: num }) }).catch(console.error); } // Наблюдатель пересечения для отслеживания показов document.addEventListener("DOMContentLoaded", () => { const options = { root: null, rootMargin: "0px", threshold: 0.5 }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const num = entry.target.getAttribute("data-num"); // Получаем data-num из элемента <a> if (num) { trackView(num); } observer.unobserve(entry.target); // Отменяем наблюдение после первого показа } }); }, options); document.querySelectorAll("a[data-num]").forEach(banner => { // Наблюдатель пересечения для учета показа observer.observe(banner); // Событие click для учета клика banner.addEventListener("click", (event) => { const num = banner.getAttribute("data-num"); if (num) { trackClick(num); } }); }); }); </script> <script> document.querySelectorAll('a, button').forEach(el => { el.addEventListener('click', () => { if (typeof gtag === 'function') { gtag('event', 'click', { event_category: 'interaction', event_label: el.dataset.role || el.dataset.href || 'unknown', value: 1 }); } }); }); </script> <script> window.addEventListener('load', function() { const body = document.body; const bg = body.getAttribute('data-bg'); // Загружать фон ТОЛЬКО если экран меньше 1024px if (window.innerWidth < 1024 && bg) { body.style.backgroundImage = `url("${bg}")`; body.style.backgroundRepeat = 'no-repeat'; body.style.backgroundPosition = 'top center'; body.style.backgroundAttachment = 'scroll'; // лучше для мобильных } }); </script> </body> </html>