PageSourceSearch

https://magictowns.al/wp-content/plugins/translatepress-developer/…/assets/js/trp-language-cookie.js?ver=1.1.1

js magictowns.al collected 2026-10-02 21:44:31 UTC 26,138 bytes, 638 lines download raw bytes

1/**
2 * Sets proper language cookie
3 *
4 * Sends ajax request to get browser and IP language.
5 * Sets cookie with current language.
6 * Changes cookie when clicking a link pointed to another language.
7 *
8 */
9function TRP_IN_Determine_Language(){
10    var _this = this;
11    var trpCookie = null;
12    var trpHelper = null;
13
14    this.get_lang_from_url = function ( url ) {
15        // Check domain mappings first if Multiple Domains is active
16        if ( trp_language_cookie_data['domain_language_map'] ) {
17            var domainLang = _this.get_lang_from_domain( url );
18            if ( domainLang ) {
19                return domainLang;
20            }
21        }
22
23        // Fall back to path-based detection
24        // we remove http or https
25        // if the user links to a http link but the abs_home_url is https, we're serving the https one so we don't brake cookies if he doesn't have proper redirects
26        var lang = url.replace( /^(http|https):\/\//g, '');
27        var abs_home = trp_language_cookie_data[ 'abs_home' ].replace( /^(http|https):\/\//g, '');
28
29        // we have removed the home path from our URL. We're adding a / in case it's the homepage of one of the languages
30        // removing / from the front so it's easier for understanding explode()
31        lang = trpHelper.ltrim( trpHelper.trailingslashit( lang.replace(abs_home, '') ),'/' );
32
33        // We now have to see if the first part of the string is actually a language slug
34        var lang_array = lang.split("/");
35        if( lang_array.length < 2 ){
36            return trp_language_cookie_data['default_language'];
37        }
38        // The language code is the first non-empty item in this array depending on abs_home slashes
39        for ( var i = 0; i < lang_array.length; i++ ){
40            if ( lang_array[i] != undefined && lang_array[i] != '' ) {
41                lang = lang_array[i];
42                break;
43            }
44        }
45        // the lang slug != actual lang. So we need to do array_search so we don't end up with en instead of en_US
46        if( trpHelper.in_array( lang, trp_language_cookie_data['url_slugs']) ){
47            return trpHelper.array_search(lang, trp_language_cookie_data['url_slugs'] );
48        } else {
49            return trp_language_cookie_data['default_language'];
50        }
51
52    };
53
54    /**
55     * Extract language from URL's domain using domain_language_map
56     * Used when Multiple Domains addon is active
57     *
58     * @param {string} url - URL to extract domain from
59     * @return {string|null} Language code or null if not found
60     */
61    this.get_lang_from_domain = function( url ) {
62        var domainMap = trp_language_cookie_data['domain_language_map'];
63        if ( !domainMap ) {
64            return null;
65        }
66
67        // Extract hostname from URL
68        var hostname;
69        try {
70            var urlObj = new URL( url );
71            hostname = urlObj.hostname;
72        } catch ( e ) {
73            // Fallback for older browsers or malformed URLs
74            var match = url.match( /^(?:https?:\/\/)?([^\/]+)/i );
75            hostname = match ? match[1] : null;
76        }
77
78        if ( !hostname ) {
79            return null;
80        }
81
82        // Check if hostname matches any configured domain
83        if ( domainMap[hostname] ) {
84            return domainMap[hostname];
85        }
86
87        return null;
88    };
89
90    this.get_current_dom_language = function(){
91        var html_language_document = document.getElementById("tp-language");
92        var html_language;
93        if ( html_language_document ){
94            if ( jQuery('#tp-language').attr('data-tp-language') ){
95                html_language = jQuery( '#tp-language' ).attr( 'data-tp-language' );
96            }else if (jQuery('#tp-language').attr('lang') ){
97                html_language = jQuery( '#tp-language' ).attr( 'lang' );
98            }
99        } else {
100            html_language = jQuery('html').attr('lang');
101            html_language = html_language.split("-").join("_");
102        }
103
104        if ( !trpHelper.in_array( html_language, trp_language_cookie_data['publish_languages'] ) ){
105            html_language = "error_determining_language";
106        }
107
108        return html_language;
109    };
110
111
112    this.ajax_get_needed_language = function() {
113        jQuery.ajax({
114            url: trp_language_cookie_data['trp_ald_ajax_url'],
115            type: 'post',
116            dataType: 'json',
117            data: {
118                action: 'trp_ald_get_needed_language',
119                detection_method: trp_language_cookie_data['detection_method'],
120                popup_option: trp_language_cookie_data['popup_option'],
121                popup_textarea: trp_language_cookie_data['popup_textarea'],
122                popup_type: trp_language_cookie_data['popup_type'],
123                popup_textarea_change_button: trp_language_cookie_data['popup_textarea_change_button'],
124                popup_textarea_close_button: trp_language_cookie_data['popup_textarea_close_button'],
125                publish_languages: trp_language_cookie_data['publish_languages'],
126                iso_codes: trp_language_cookie_data['iso_codes'],
127                english_name: trp_language_cookie_data['english_name'],
128                default_language: trp_language_cookie_data['default_language'],
129                is_iphone_user_check: trp_language_cookie_data['is_iphone_user_check']
130            },
131            success: function( response ) {
132                if ( response ) {
133                    _this.redirect_if_needed( response );
134                }else{
135                    _this.redirect_if_needed( _this.get_current_dom_language() );
136                }
137
138            },
139            error: function( errorThrown ){
140                // make current language the needed language
141                _this.redirect_if_needed( _this.get_current_dom_language() );
142            }
143        });
144    };
145
146    this.activate_popup = function( response, url_to_redirect ){
147
148        _this.make_ls_clickable();
149        _this.ls_make_default_language_preselected( response );
150
151        var popup = document.getElementById("trp_ald_modal_container");
152        var close = document.getElementById("trp_ald_x_button");
153        var popup_change_button = document.getElementById("trp_ald_popup_change_language");
154        var close_popup = document.getElementById("trp_ald_x_button_and_textarea");
155        var no_text_popup_select_current_language = document.querySelector('[special-selector = "trp_ald_popup_current_language"]');
156
157        popup.style.display = 'block';
158
159        close_popup.onclick = function(e){
160            popup.style.display = 'none';
161            trpCookie.setCookie( trp_language_cookie_data['cookie_name'], _this.get_current_dom_language(), trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'] );
162
163            // Anchor looks like this <a href="#">. This prevents navigating to #
164            e.preventDefault();
165        }
166
167        _this.ls_select_language();
168
169        popup_change_button.onclick = function(){
170            var selected_language = no_text_popup_select_current_language.getAttribute('data-trp-ald-selected-language');
171            trpCookie.setCookie( trp_language_cookie_data['cookie_name'], selected_language, trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'] );
172        }
173    }
174
175
176    this.activate_hello_bar = function (response, url_to_redirect){
177
178        var no_text_popup = document.getElementById("trp_ald_no_text_popup_template");
179        var clone = no_text_popup.content.cloneNode(true);
180
181        var close_button = clone.getElementById('trp_close');
182        var button_change_language_no_text_popup = clone.getElementById('trp_ald_no_text_popup_change_language');
183        var no_text_popup_select_current_language = clone.querySelector('[special-selector = "trp_ald_popup_current_language"]');
184
185        var div = document.createElement('div');
186        div.appendChild(clone);
187        document.body.insertAdjacentElement('afterbegin', div);
188
189        button_change_language_no_text_popup.onclick = function() {
190            var selected_language = no_text_popup_select_current_language.getAttribute( 'data-trp-ald-selected-language' );
191            trpCookie.setCookie( trp_language_cookie_data[ 'cookie_name' ], selected_language, trp_language_cookie_data[ 'cookie_age' ], trp_language_cookie_data[ 'cookie_path' ] );
192        }
193
194        var remove_bar = function () {
195            trpCookie.setCookie( trp_language_cookie_data['cookie_name'], _this.get_current_dom_language(), trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'] );
196            document.body.removeChild(div);
197        };
198
199        close_button.onclick = remove_bar;
200
201        _this.make_ls_clickable();
202        _this.ls_select_language();
203        _this.ls_make_default_language_preselected( response );
204    }
205
206
207    this.make_ls_clickable = function (){
208        jQuery('.trp_ald_ls_container .trp-ls-shortcode-current-language').click(function () {
209            jQuery( '.trp_ald_ls_container .trp-ls-shortcode-current-language' ).addClass('trp-ls-clicked');
210            jQuery( '.trp_ald_ls_container .trp-ls-shortcode-language' ).addClass('trp-ls-clicked');
211        });
212
213        jQuery('.trp_ald_ls_container .trp-ls-shortcode-language').click(function () {
214            jQuery( '.trp_ald_ls_container .trp-ls-shortcode-current-language' ).removeClass('trp-ls-clicked');
215            jQuery( '.trp_ald_ls_container .trp-ls-shortcode-language' ).removeClass('trp-ls-clicked');
216        });
217
218
219        jQuery(document).keyup(function(e) {
220            if (e.key === "Escape") {
221                jQuery( '.trp_ald_ls_container .trp-ls-shortcode-current-language' ).removeClass('trp-ls-clicked');
222                jQuery( '.trp_ald_ls_container .trp-ls-shortcode-language' ).removeClass('trp-ls-clicked');
223            }
224        });
225
226        jQuery(document).on("click", function(event){
227            if(!jQuery(event.target).closest(".trp_ald_ls_container .trp-ls-shortcode-current-language").length){
228                jQuery( '.trp_ald_ls_container .trp-ls-shortcode-current-language' ).removeClass('trp-ls-clicked');
229                jQuery( '.trp_ald_ls_container .trp-ls-shortcode-language' ).removeClass('trp-ls-clicked');
230            }
231        });
232    }
233
234    this.ls_select_language = function(){
235        
236        var no_text_current_language = document.querySelector('.trp_ald_ls_container .trp-ls-shortcode-current-language');
237        var no_text_popup_select_current_language = document.querySelector('.trp_ald_ls_container .trp-ls-shortcode-current-language');
238        var popup_change_button = document.getElementById("trp_ald_popup_change_language");
239        var button_change_language_no_text_popup = document.getElementById('trp_ald_no_text_popup_change_language');
240        jQuery('.trp-ald-popup-select').click(function ( item ) {
241            no_text_current_language.innerHTML = item.target.innerHTML;
242            no_text_current_language.setAttribute('data-trp-ald-selected-language', item.target.getAttribute('data-trp-ald-selected-language'));
243            var selected_language = no_text_popup_select_current_language.getAttribute('data-trp-ald-selected-language');
244            _this.set_language_href(selected_language,popup_change_button,button_change_language_no_text_popup);
245        });
246    }
247
248    this.ls_make_default_language_preselected = function( response ){
249
250        var no_text_current_language = document.querySelector('[special-selector = "trp_ald_popup_current_language"]');
251        var all_languages = document.querySelectorAll('.trp_ald_ls_container .trp-ald-popup-select');
252        var popup_change_button = document.getElementById("trp_ald_popup_change_language");
253        var button_change_language_no_text_popup = document.getElementById('trp_ald_no_text_popup_change_language');
254        for ( var i = 0; i< all_languages.length; i++){
255            if (all_languages[i].id === response){
256                no_text_current_language.innerHTML = all_languages[i].innerHTML;
257                no_text_current_language.setAttribute('data-trp-ald-selected-language', response);
258                no_text_current_language.setAttribute('id', response);
259                var selected_language = no_text_current_language.getAttribute('data-trp-ald-selected-language');
260                _this.set_language_href(selected_language, popup_change_button, button_change_language_no_text_popup);
261                break;
262            }
263        }
264    }
265
266    this.set_language_href = function ( selected_language, popup_change_button, button_change_language_no_text_popup ){
267        if( popup_change_button !== null ){
268            popup_change_button.href = _this.get_url_for_lang(selected_language);
269        }
270        if( button_change_language_no_text_popup !== null ){
271            button_change_language_no_text_popup.href = _this.get_url_for_lang(selected_language);
272        }
273    }
274
275    this.decode_HTML_entities = function(str) {
276        let txt = new DOMParser().parseFromString(str, "text/html");
277        return txt.documentElement.textContent;
278    }
279
280    this.get_url_for_lang = function( language ){
281
282        for( i in trp_language_cookie_data['language_urls'] ){
283            if( i === language ) {
284                let url_for_language = _this.decode_HTML_entities(trp_language_cookie_data['language_urls'][i]);
285
286                return url_for_language;
287            }
288        }
289        return false;
290    };
291
292    this.is_valid_url = function ( url ) {
293        if ( typeof url === 'undefined' || url === '' ){
294            return false;
295        }
296        var starting_characters = ['#','?', 'javascript'];
297        for (var i = 0; i < starting_characters.length; i++ ){
298            if ( url.substring(0, starting_characters[i].length) === starting_characters[i]){
299                return false;
300            }
301        }
302        return true;
303    };
304
305    this.replace_underscore_with_dash = function (var_replace){
306        var_replace = var_replace.toLowerCase();
307        var_replace = var_replace.split("_").join("-");
308
309        return var_replace;
310    }
311
312    this.is_same_language_code = function (var1, var2){
313        var1 = _this.replace_underscore_with_dash(var1);
314        var2 = _this.replace_underscore_with_dash(var2);
315
316        if( var1 == var2 || var1 == "error_determining_language" || var2 == "error_determining_language" ){
317            return true;
318        }
319        return false;
320    }
321
322    this.is_login_url = function( url ){
323        if( url.includes( "wp-login.php" )){
324            return true;
325        }
326        return false;
327    }
328
329    this.add_event_handlers = function(){
330        jQuery('body').on('click', 'a', function(e) {
331
332            var clicked_url = jQuery(this).attr("href");
333            if ( _this.is_valid_url( clicked_url ) && !_this.is_login_url( clicked_url )) {
334                var clicked_language = _this.get_lang_from_url(clicked_url);
335                var trp_current_language = trpCookie.getCookie(trp_language_cookie_data['cookie_name']);
336
337                if (!(_this.is_same_language_code(trp_current_language, clicked_language))) {
338                    // When Multiple Domains is active, only handle clicks to our configured domains
339                    if ( trp_language_cookie_data['domain_language_map'] && !_this.get_lang_from_domain( clicked_url ) ) {
340                        return; // External URL — don't change cookie or add trp_lang_switch
341                    }
342
343                    // Skip cross-domain sync here — the landing page will handle it after detecting trp_lang_switch=1
344                    trpCookie.setCookie(trp_language_cookie_data['cookie_name'], clicked_language, trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'], true);
345
346                    // Add query param to signal deliberate language switch (for cross-domain)
347                    if ( trp_language_cookie_data['domain_language_map'] ) {
348                        e.preventDefault();
349                        var separator = clicked_url.indexOf('?') !== -1 ? '&' : '?';
350                        window.location.href = clicked_url + separator + 'trp_lang_switch=1';
351                        return false;
352                    }
353                }
354            }
355        });
356    };
357
358    this.check_if_iphone_user = function (){
359        
360        if( trp_language_cookie_data['is_iphone_user_check'] == false ){
361            return false;
362        }else{
363            if( /iPhone/g.test(navigator.userAgent) ){
364                return true;
365            }else{
366                return false;
367            }
368        }
369    };
370
371    this.redirect_if_needed = function( needed_language ){
372        // Skip cross-domain sync here — if redirect happens the landing page handles it, if not the cookie is already correct
373        trpCookie.setCookie( trp_language_cookie_data['cookie_name'], needed_language, trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'], true );
374        _this.add_event_handlers();
375
376        if (!(_this.is_same_language_code(_this.get_current_dom_language(), needed_language)) && _this.check_if_iphone_user() == false ){
377            url_to_redirect = _this.get_url_for_lang( needed_language );
378            if(url_to_redirect != 'undefined' && url_to_redirect!= false ) {
379                // redirect to needed language
380                if(trp_language_cookie_data['popup_type'] == 'normal_popup' && trp_language_cookie_data['popup_option'] == 'popup'){
381                    _this.activate_popup( needed_language, url_to_redirect );
382                }else{
383                    if(trp_language_cookie_data['popup_type'] == 'hello_bar' && trp_language_cookie_data['popup_option'] == 'popup'){
384                        _this.activate_hello_bar(needed_language, url_to_redirect);
385                    }else {
386                        window.location.replace( url_to_redirect );
387                    }
388                }
389            }
390        }
391    };
392
393    this.initialize = function (){
394        trpCookie = new TRP_IN_Cookie();
395        trpHelper = new TRP_IN_Helper();
396        if ( ! trpCookie.areCookiesEnabled() ){
397            _this.add_event_handlers();
398            return;
399        }
400
401        // Check if this is a deliberate language switch (query param from add_event_handlers)
402        var urlParams = new URLSearchParams( window.location.search );
403        if ( urlParams.has( 'trp_lang_switch' ) ) {
404            // Remove the query param from URL first
405            urlParams.delete( 'trp_lang_switch' );
406            var newUrl = window.location.pathname + ( urlParams.toString() ? '?' + urlParams.toString() : '' ) + window.location.hash;
407            history.replaceState( null, '', newUrl );
408
409            // Deliberate switch - set cookie to current page language, no popup
410            var currentLanguage = _this.get_lang_from_url( window.location.href );
411            if ( currentLanguage ) {
412                trpCookie.setCookie( trp_language_cookie_data['cookie_name'], currentLanguage, trp_language_cookie_data['cookie_age'], trp_language_cookie_data['cookie_path'] );
413                _this.add_event_handlers();
414                return;
415            }
416            // If no domain language found (Multiple Domains not active), continue with normal detection
417        }
418
419        var language_from_cookie = trpCookie.getCookie( trp_language_cookie_data['cookie_name'] );
420        if ( language_from_cookie && trpHelper.in_array( language_from_cookie, trp_language_cookie_data['publish_languages'] ) ) {
421            // if cookie is set, redirect if needed
422            _this.redirect_if_needed( language_from_cookie );
423        }else{
424            // if cookie is not set, send request to find out language and then redirect if needed
425            _this.ajax_get_needed_language();
426        }
427    };
428
429    _this.initialize();
430}
431
432/**
433 * String manipulation functions
434 */
435function TRP_IN_Helper(){
436
437    this.trailingslashit = function ( string ){
438        string = string.replace(/\/+$/,'');
439        string = string + '/';
440        return string;
441    };
442
443    this.ltrim = function ( string ) {
444        var trimmed = string.replace(/^\s+/g, '');
445        return trimmed;
446    };
447
448    this.in_array = function (needle, haystack) {
449        for(var i in haystack ) {
450            if(haystack[i] == needle) {
451                return true;
452            }
453        }
454        return false;
455    };
456
457    this.array_search = function(val, array) {
458        if(typeof(array) === 'array' || typeof(array) === 'object') {
459            var rekey;
460            for(var i in array) {
461                if(array[i] == val) {
462                    rekey = i;
463                    break;
464                }
465            }
466            return rekey;
467        }
468    };
469
470    /**
471     * Update url with query string.
472     *
473     */
474    this.update_query_string = function(key, value, url) {
475        if (!url) url = window.location.href;
476        var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
477            hash;
478
479        if (re.test(url)) {
480            if (typeof value !== 'undefined' && value !== null)
481                return url.replace(re, '$1' + key + "=" + value + '$2$3');
482            else {
483                hash = url.split('#');
484                url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
485                if (typeof hash[1] !== 'undefined' && hash[1] !== null)
486                    url += '#' + hash[1];
487                return url;
488            }
489        }
490        else {
491            if (typeof value !== 'undefined' && value !== null ) {
492                var separator = url.indexOf('?') !== -1 ? '&' : '?';
493                hash = url.split('#');
494                url = hash[0] + separator + key + '=' + value;
495                if (typeof hash[1] !== 'undefined' && hash[1] !== null)
496                    url += '#' + hash[1];
497                return url;
498            }
499            else
500                return url;
501        }
502    };
503}
504
505/**
506 * Manipulate cookie: set/get/erase
507 * Includes cross-domain sync for Multiple Domains addon
508 */
509function TRP_IN_Cookie() {
510    var _this = this;
511
512    // Track if sync is in progress to prevent duplicate syncs
513    this.syncInProgress = false;
514
515    /**
516     * Set a cookie and trigger cross-domain sync if enabled
517     *
518     * @param {boolean} skipSync - Skip cross-domain sync (e.g. when navigating away immediately)
519     */
520    this.setCookie = function(cname, cvalue, exdays, cpath, skipSync) {
521        var d = new Date();
522        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
523        var expires = "expires=" + d.toUTCString();
524        document.cookie = cname + "=" + cvalue + ";" + expires + ";path=" + cpath + ";SameSite=Lax";
525
526        // Trigger cross-domain sync if this is the language cookie
527        if ( cname === trp_language_cookie_data['cookie_name'] && !skipSync ) {
528            _this.syncToOtherDomains( cvalue );
529        }
530    };
531
532    this.getCookie = function(cname) {
533        var name = cname + "=";
534        var ca = document.cookie.split(';');
535        for(var i = 0; i < ca.length; i++) {
536            var c = ca[i];
537            while (c.charAt(0) == ' ') {
538                c = c.substring(1);
539            }
540            if (c.indexOf(name) == 0) {
541                return c.substring(name.length, c.length);
542            }
543        }
544        return "";
545    };
546
547    this.eraseCookie = function(name) {
548        document.cookie = name+'=; Max-Age=-99999999;';
549    };
550
551    this.areCookiesEnabled = function(){
552        if (navigator.cookieEnabled) return true;
553
554        // set and read cookie
555        document.cookie = "cookietest=1";
556        var ret = document.cookie.indexOf("cookietest=") != -1;
557
558        // delete cookie
559        document.cookie = "cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT";
560
561        return ret;
562    };
563
564    /**
565     * Sync cookie to all other configured domains (Multiple Domains support)
566     *
567     * @param {string} cookieValue - The language code to sync
568     */
569    this.syncToOtherDomains = function( cookieValue ) {
570        // Check if sync is enabled and ajax URLs exist
571        if ( !trp_language_cookie_data['sync_enabled'] ||
572             !trp_language_cookie_data['sync_ajax_urls'] ||
573             _this.syncInProgress ) {
574            return;
575        }
576
577        _this.syncInProgress = true;
578
579        var currentDomain = trp_language_cookie_data['current_domain'];
580        var ajaxUrls = trp_language_cookie_data['sync_ajax_urls'];
581
582        for ( var language in ajaxUrls ) {
583            if ( !ajaxUrls.hasOwnProperty( language ) ) {
584                continue;
585            }
586
587            var ajaxUrl = ajaxUrls[ language ];
588
589            // Skip if this ajax URL is on the current domain
590            if ( ajaxUrl.indexOf( currentDomain ) === 0 ) {
591                continue;
592            }
593
594            _this.injectSyncIframe( ajaxUrl, cookieValue );
595        }
596
597        // Reset sync flag after a delay
598        setTimeout( function() {
599            _this.syncInProgress = false;
600        }, 5000 );
601    };
602
603    /**
604     * Inject hidden iframe to set cookie on another domain via REST API
605     *
606     * @param {string} restUrl - Target REST API URL
607     * @param {string} cookieValue - Cookie value to set
608     */
609    this.injectSyncIframe = function( restUrl, cookieValue ) {
610        var iframe = document.createElement( 'iframe' );
611        iframe.style.display = 'none';
612        iframe.className = 'trp-ald-sync-iframe';
613        iframe.src = restUrl + '?trp_ald_cv=' + encodeURIComponent( cookieValue );
614
615        // Remove iframe after load or timeout
616        iframe.onload = function() {
617            setTimeout( function() {
618                if ( iframe.parentNode ) {
619                    iframe.parentNode.removeChild( iframe );
620                }
621            }, 1000 );
622        };
623
624        // Fallback: remove after timeout even if onload doesn't fire
625        setTimeout( function() {
626            if ( iframe.parentNode ) {
627                iframe.parentNode.removeChild( iframe );
628            }
629        }, 10000 );
630
631        document.body.appendChild( iframe );
632    };
633}
634
635
636jQuery( function() {
637    trpDetermineLanguage = new TRP_IN_Determine_Language();
638});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.