Skip to main content

GTranslate

is it possible that the GTranslate plugin is not working on the portal pages?

https://wordpress.org/plugins/gtranslate/

it is one of the most used translate plugins

Han Van

add this code to your function.php of your theme under // Add your own custom functions here:

add_action('fluent_community/portal_head', function () { ?> <div class="gtranslate_wrapper"></div> <script> window.gtranslateSettings = { "default_language": "en", "languages": ["en", "es", "fr", "de", "it"], "wrapper_selector": ".gtranslate_wrapper", "flag_style": "2d", "float_switcher_open_direction": "bottom", "switcher_horizontal_position": "right", "switcher_vertical_position": "top" }; </script> <script src="https://cdn.gtranslate.net/widgets/latest/float.js" defer></script> <?php });

Han Van

even nicer, now it doesn't matter what language is written and some nice css:

add_action('fluent_community/portal_head', function () {
// Server-side: WordPress locale as primary fallback
$wp_locale = get_locale();
$lang_code = explode('_', $wp_locale)\[0];
$supported = \['en', 'es', 'nl', 'de', 'zh-TW'];
$site_lang = in_array($lang_code, $supported) ? $lang_code : 'nl';
?> 

<style>
<a data-user_name="media" class="fcom_mention fcom_route" href="https://community.wpmanageninja.com/portal/u/media/">Media Rocketeer</a> screen and (max-width: 1024px) { .gt_float_switcher {    margin-bottom: 60px;
}}

    /* GTranslate wrapper positioning */
    .gtranslate_wrapper {
        position: fixed;
        bottom: 20px;
        right: 20px;
        z-index: 99999;
    }

    /* Style the language selector dropdown */
    .gt-lang-code {
        font-family: inherit;
        font-size: 13px;
    }

    /* Hide the Google Translate top banner */
    .skiptranslate,
    #goog-gt-tt,
    .goog-te-banner-frame {
        display: none !important;
    }

    /* Prevent body shift caused by Google's injected toolbar */
    body {
        top: 0 !important;
    }

    /* Optional: style the flag switcher button */
    <a data-user_name="media" class="fcom_mention fcom_route" href="https://community.wpmanageninja.com/portal/u/media/">Media Rocketeer</a> screen and (max-width: 1024px) { .gt-current-lang {
        border-radius: 6px;
        color: #fff;
        font-size: 13px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
        width:50px!important;
        padding-left: 10px !important;
        margin-bottom: -47px !important;

    }}
</style>


<div class="gtranslate_wrapper"></div>
<script>
    const supportedLanguages = ["en", "es", "nl", "de", "zh-TW"];

    // WordPress site locale passed from PHP (server-side fallback)
    const siteLang = "<?php echo esc_js($site_lang); ?>";

    // ─── Content-based language detection ────────────────────────────────

    // Latin-script stopword fingerprints
    const latinFingerprints = {
        en: ["the","and","is","in","it","of","to","a","that","was","for","on","are","with","he","she","they","this","at","be"],
        es: ["el","la","los","las","es","en","de","que","y","un","una","por","con","se","su","del","al","lo","le","más"],
        nl: ["de","het","een","en","van","is","in","dat","op","te","zijn","met","niet","aan","er","ook","maar","om","ze","hij"],
        de: ["der","die","das","und","ist","in","von","zu","den","ein","eine","mit","auf","dem","sich","des","nicht","es","an","war"],
    };

    // Chinese character ranges (Traditional & Simplified share same Unicode blocks)
    // We detect Chinese by the presence of CJK characters
    function isChinese(text) {
        // CJK Unified Ideographs block: \u4E00-\u9FFF
        // CJK Extension A: \u3400-\u4DBF
        // CJK Compatibility: \uF900-\uFAFF
        const cjkPattern = /[\u4E00-\u9FFF\u3400-\u4DBF\uF900-\uFAFF]/g;
        const cjkChars   = (text.match(cjkPattern) || []).length;
        const totalChars  = text.replace(/\s/g, "").length;
        // Consider Chinese if >15% of non-whitespace chars are CJK
        return totalChars > 0 && (cjkChars / totalChars) > 0.15;
    }

    // Traditional vs Simplified Chinese detection
    // Traditional-only characters that are not used in Simplified
    function isTraditionalChinese(text) {
        const traditionalChars = [
            "的","是","在","不","了","有","和","人","這","中",
            "為","個","上","來","說","國","時","會","對","發",
            "們","學","後","以","見","可","她","麼","說","到",
            "著","從","動","進","面","子","開","裡","後","門",
            "還","沒","現","實","點","讓","問","過","年","大",
            "間","長","們","兒","關","將","歡","樣","華","業"
        ];
        const simplifiedChars = [
            "这","国","时","会","发","们","说","动","进","里",
            "还","没","现","实","让","过","间","长","儿","关",
            "将","欢","样","华","业","点","问"
        ];
        let tradScore = 0;
        let simpScore = 0;
        for (const ch of text) {
            if (traditionalChars.includes(ch)) tradScore++;
            if (simplifiedChars.includes(ch)) simpScore++;
        }
        // Prefer Traditional if trad score >= simplified score
        return tradScore >= simpScore;
    }

    function detectContentLanguage(text) {
        if (!text || text.trim().length < 20) return null;

        // ── Step 1: Check for Chinese characters first ──
        if (isChinese(text)) {
            // Map to zh-TW (Traditional) since that's in your supported list
            // If you also want zh-CN, add it to supportedLanguages
            return "zh-TW";
        }

        // ── Step 2: Latin-script stopword fingerprinting ──
        const words = text
            .toLowerCase()
            .replace(/[^a-záéíóúàèìòùäöüçñœæ\s]/gi, "")
            .split(/\s+/)
            .filter(Boolean);

        if (words.length < 5) return null;

        const scores = {};
        for (const [lang, stopwords] of Object.entries(latinFingerprints)) {
            const hits    = words.filter(w => stopwords.includes(w)).length;
            scores[lang]  = hits / words.length;
        }

        const best = Object.entries(scores).sort((a, b) => b[1] - a[1])[0];

        // Only trust if above threshold
        return best[1] > 0.02 ? best[0] : null;
    }

    function extractPageText() {
        const selectors = [
            "h1", "h2", "h3", "h4",
            "p", "article", "main",
            ".fcom_post_content",
            ".fcom_feed_content",
            ".fcom-content"
        ];

        return selectors
            .flatMap(sel => [...document.querySelectorAll(sel)])
            .filter(el => !el.closest(".gtranslate_wrapper"))
            .map(el => el.innerText || el.textContent || "")
            .join(" ")
            .trim();
    }

    function initGTranslate(lang) {
        window.gtranslateSettings = {
            "default_language": lang,
            "languages": supportedLanguages,
            "language_names_in_native_language": true,
            "native_language_names": {
                "en":    "English",
                "es":    "Español",
                "nl":    "Nederlands",
                "de":    "Deutsch",
                "zh-TW": "繁體中文"
            },
            "wrapper_selector":              ".gtranslate_wrapper",
            "flag_style":                    "2d",
            "float_switcher_open_direction": "top",
            "switcher_horizontal_position":  "left",
            "switcher_vertical_position":    "bottom"
        };
    }

    function saveLangChoice() {
        document.querySelectorAll(".gt-lang-code").forEach(function (el) {
            el.addEventListener("click", function () {
                const chosen = el.getAttribute("data-lang");
                if (chosen) localStorage.setItem("gtranslate_lang", chosen);
            });
        });
    }

    // ─── Language priority chain ──────────────────────────────────────────
    // 1. User's saved manual choice (localStorage)
    // 2. Content-based detection:
    //      a. CJK character ratio → zh-TW
    //      b. Traditional vs Simplified scoring → zh-TW confirmed
    //      c. Latin stopword fingerprinting → en / es / nl / de
    // 3. WordPress site locale (server-side)
    // 4. English fallback

    const savedLang = localStorage.getItem("gtranslate_lang");

    if (savedLang && supportedLanguages.includes(savedLang)) {
        // Priority 1: respect previous manual choice immediately
        initGTranslate(savedLang);
        saveLangChoice();
    } else {
        // Priority 2: detect from page content after DOM is ready
        document.addEventListener("DOMContentLoaded", function () {
            const pageText  = extractPageText();
            const detected  = detectContentLanguage(pageText);

            const finalLang = (detected && supportedLanguages.includes(detected))
                ? detected
                : siteLang;

            initGTranslate(finalLang);
            saveLangChoice();

            // Load GTranslate script dynamically after detection
            const script  = document.createElement("script");
            script.src    = "https://cdn.gtranslate.net/widgets/latest/float.js";
            script.defer  = true;
            document.head.appendChild(script);
        });
    }
</script>

<?php
});

Han Van

i don't think you need the plugin