Google Language Switcher

Save and apply language preferences for Google Search, Maps, and YouTube

// ==UserScript==
// @match        *://*.google.com/*
// @match        *://*.google.ad/*
// @match        *://*.google.ae/*
// @match        *://*.google.com.af/*
// @match        *://*.google.com.ag/*
// @match        *://*.google.com.ai/*
// @match        *://*.google.al/*
// @match        *://*.google.am/*
// @match        *://*.google.co.ao/*
// @match        *://*.google.com.ar/*
// @match        *://*.google.as/*
// @match        *://*.google.at/*
// @match        *://*.google.com.au/*
// @match        *://*.google.az/*
// @match        *://*.google.ba/*
// @match        *://*.google.com.bd/*
// @match        *://*.google.be/*
// @match        *://*.google.bf/*
// @match        *://*.google.bg/*
// @match        *://*.google.com.bh/*
// @match        *://*.google.bi/*
// @match        *://*.google.bj/*
// @match        *://*.google.com.bn/*
// @match        *://*.google.com.bo/*
// @match        *://*.google.com.br/*
// @match        *://*.google.bs/*
// @match        *://*.google.bt/*
// @match        *://*.google.co.bw/*
// @match        *://*.google.by/*
// @match        *://*.google.com.bz/*
// @match        *://*.google.ca/*
// @match        *://*.google.cd/*
// @match        *://*.google.cf/*
// @match        *://*.google.cg/*
// @match        *://*.google.ch/*
// @match        *://*.google.ci/*
// @match        *://*.google.co.ck/*
// @match        *://*.google.cl/*
// @match        *://*.google.cm/*
// @match        *://*.google.cn/*
// @match        *://*.google.com.co/*
// @match        *://*.google.co.cr/*
// @match        *://*.google.com.cu/*
// @match        *://*.google.cv/*
// @match        *://*.google.com.cy/*
// @match        *://*.google.cz/*
// @match        *://*.google.de/*
// @match        *://*.google.dj/*
// @match        *://*.google.dk/*
// @match        *://*.google.dm/*
// @match        *://*.google.com.do/*
// @match        *://*.google.dz/*
// @match        *://*.google.com.ec/*
// @match        *://*.google.ee/*
// @match        *://*.google.com.eg/*
// @match        *://*.google.es/*
// @match        *://*.google.com.et/*
// @match        *://*.google.fi/*
// @match        *://*.google.com.fj/*
// @match        *://*.google.fm/*
// @match        *://*.google.fr/*
// @match        *://*.google.ga/*
// @match        *://*.google.ge/*
// @match        *://*.google.gg/*
// @match        *://*.google.com.gh/*
// @match        *://*.google.com.gi/*
// @match        *://*.google.gl/*
// @match        *://*.google.gm/*
// @match        *://*.google.gr/*
// @match        *://*.google.com.gt/*
// @match        *://*.google.gy/*
// @match        *://*.google.com.hk/*
// @match        *://*.google.hn/*
// @match        *://*.google.hr/*
// @match        *://*.google.ht/*
// @match        *://*.google.hu/*
// @match        *://*.google.co.id/*
// @match        *://*.google.ie/*
// @match        *://*.google.co.il/*
// @match        *://*.google.im/*
// @match        *://*.google.co.in/*
// @match        *://*.google.iq/*
// @match        *://*.google.is/*
// @match        *://*.google.it/*
// @match        *://*.google.je/*
// @match        *://*.google.com.jm/*
// @match        *://*.google.jo/*
// @match        *://*.google.co.jp/*
// @match        *://*.google.co.ke/*
// @match        *://*.google.com.kh/*
// @match        *://*.google.ki/*
// @match        *://*.google.kg/*
// @match        *://*.google.co.kr/*
// @match        *://*.google.com.kw/*
// @match        *://*.google.kz/*
// @match        *://*.google.la/*
// @match        *://*.google.com.lb/*
// @match        *://*.google.li/*
// @match        *://*.google.lk/*
// @match        *://*.google.co.ls/*
// @match        *://*.google.lt/*
// @match        *://*.google.lu/*
// @match        *://*.google.lv/*
// @match        *://*.google.com.ly/*
// @match        *://*.google.co.ma/*
// @match        *://*.google.md/*
// @match        *://*.google.me/*
// @match        *://*.google.mg/*
// @match        *://*.google.mk/*
// @match        *://*.google.ml/*
// @match        *://*.google.com.mm/*
// @match        *://*.google.mn/*
// @match        *://*.google.ms/*
// @match        *://*.google.com.mt/*
// @match        *://*.google.mu/*
// @match        *://*.google.mv/*
// @match        *://*.google.mw/*
// @match        *://*.google.com.mx/*
// @match        *://*.google.com.my/*
// @match        *://*.google.co.mz/*
// @match        *://*.google.com.na/*
// @match        *://*.google.com.ng/*
// @match        *://*.google.com.ni/*
// @match        *://*.google.ne/*
// @match        *://*.google.nl/*
// @match        *://*.google.no/*
// @match        *://*.google.com.np/*
// @match        *://*.google.nr/*
// @match        *://*.google.nu/*
// @match        *://*.google.co.nz/*
// @match        *://*.google.com.om/*
// @match        *://*.google.com.pa/*
// @match        *://*.google.com.pe/*
// @match        *://*.google.com.pg/*
// @match        *://*.google.com.ph/*
// @match        *://*.google.com.pk/*
// @match        *://*.google.pl/*
// @match        *://*.google.pn/*
// @match        *://*.google.com.pr/*
// @match        *://*.google.ps/*
// @match        *://*.google.pt/*
// @match        *://*.google.com.py/*
// @match        *://*.google.com.qa/*
// @match        *://*.google.ro/*
// @match        *://*.google.ru/*
// @match        *://*.google.rw/*
// @match        *://*.google.com.sa/*
// @match        *://*.google.com.sb/*
// @match        *://*.google.sc/*
// @match        *://*.google.se/*
// @match        *://*.google.com.sg/*
// @match        *://*.google.sh/*
// @match        *://*.google.si/*
// @match        *://*.google.sk/*
// @match        *://*.google.com.sl/*
// @match        *://*.google.sn/*
// @match        *://*.google.so/*
// @match        *://*.google.sm/*
// @match        *://*.google.sr/*
// @match        *://*.google.st/*
// @match        *://*.google.com.sv/*
// @match        *://*.google.td/*
// @match        *://*.google.tg/*
// @match        *://*.google.co.th/*
// @match        *://*.google.com.tj/*
// @match        *://*.google.tl/*
// @match        *://*.google.tm/*
// @match        *://*.google.tn/*
// @match        *://*.google.to/*
// @match        *://*.google.com.tr/*
// @match        *://*.google.tt/*
// @match        *://*.google.com.tw/*
// @match        *://*.google.co.tz/*
// @match        *://*.google.com.ua/*
// @match        *://*.google.co.ug/*
// @match        *://*.google.co.uk/*
// @match        *://*.google.com.uy/*
// @match        *://*.google.co.uz/*
// @match        *://*.google.com.vc/*
// @match        *://*.google.co.ve/*
// @match        *://*.google.vg/*
// @match        *://*.google.co.vi/*
// @match        *://*.google.com.vn/*
// @match        *://*.google.vu/*
// @match        *://*.google.ws/*
// @match        *://*.google.rs/*
// @match        *://*.google.co.za/*
// @match        *://*.google.co.zm/*
// @match        *://*.google.co.zw/*
// @match        *://*.google.cat/*
// @match        *://*.youtube.com/*
// @name         Google Language Switcher
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  Save and apply language preferences for Google Search, Maps, and YouTube
// @name:en      Google Language Switcher
// @description:en Save and apply language preferences for Google Search, Maps, and YouTube
// @name:es      Cambiador de idioma de Google
// @description:es Guarda y aplica preferencias de idioma para Google Search, Maps y YouTube
// @name:fr      Changeur de langue Google
// @description:fr Enregistrez et appliquez les préférences de langue pour Google Search, Maps et YouTube
// @name:de      Google-Sprachumschalter
// @description:de Speichern und Anwenden von Spracheinstellungen für Google Search, Maps und YouTube
// @name:it      Cambia lingua di Google
// @description:it Salva e applica le preferenze della lingua per Google Search, Maps e YouTube
// @name:pt      Alternador de idioma do Google
// @description:pt Salve e aplique preferências de idioma para Google Search, Maps e YouTube
// @name:ru      Переключатель языка Google
// @description:ru Сохраните и примените языковые предпочтения для Google Search, Maps и YouTube
// @name:ja      Google言語スイッチャー
// @description:ja Google検索、マップ、YouTubeの言語設定を保存して適用
// @name:ko      구글 언어 전환기
// @description:ko Google 검색, 지도 및 YouTube에 대한 언어 설정을 저장하고 적용
// @name:zh-cn   谷歌语言切换器
// @description:zh-cn 保存并应用Google搜索、地图和YouTube的语言偏好
// @name:zh-tw   谷歌語言切換器
// @description:zh-tw 保存並應用Google搜尋、地圖和YouTube的語言偏好
// @name:ar      مبدل لغة جوجل
// @description:ar احفظ وطبق تفضيلات اللغة لـ Google Search و Maps و YouTube
// @name:hi      गूगल भाषा स्विचर
// @description:hi Google Search, Maps और YouTube के लिए भाषा वरीयताओं को सहेजें और लागू करें
// @name:th      ตัวสลับภาษา Google
// @description:th บันทึกและใช้ค่ากำหนดภาษาใน Google Search, Maps และ YouTube
// @name:vi      Bộ chuyển đổi ngôn ngữ Google
// @description:vi Lưu và áp dụng các tùy chọn ngôn ngữ cho Google Search, Maps và YouTube
// @name:id      Pengalih Bahasa Google
// @description:id Simpan dan terapkan preferensi bahasa untuk Google Search, Maps, dan YouTube
// @name:ms      Penukar Bahasa Google
// @description:ms Simpan dan terapkan keutamaan bahasa untuk Google Search, Maps dan YouTube
// @name:tr      Google Dil Değiştirici
// @description:tr Google Search, Maps ve YouTube için dil tercihlerini kaydedin ve uygulayın
// @name:nl      Google Taalwisselaar
// @description:nl Sla taalvoorkeuren op en pas deze toe voor Google Zoeken, Maps en YouTube
// @name:pl      Przełącznik języka Google
// @description:pl Zapisz i zastosuj preferencje językowe dla Google Search, Maps i YouTube
// @author       TieuThanhNhi
// @copyright    2024, TieuThanhNhi (https://greasyfork.org/users/1195312)
// @license      MIT
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    const LANG_PARAM = 'hl';
    const STORAGE_KEY = 'googleLang';
    const SUPPORTED_DOMAINS = [
        'google.com',
        'youtube.com',
        'google.ad',
        'google.ae',
        'google.com.af',
        // ... (add other Google domains here)
    ];

    const languages = [
        { code: 'en', name: 'English' },
        { code: 'es', name: 'Español' },
        { code: 'fr', name: 'Français' },
        { code: 'de', name: 'Deutsch' },
        { code: 'it', name: 'Italiano' },
        { code: 'pt', name: 'Português' },
        { code: 'ru', name: 'Русский' },
        { code: 'ja', name: '日本語' },
        { code: 'ko', name: '한국어' },
        { code: 'zh-CN', name: '中文 (简体)' },
        { code: 'zh-TW', name: '中文 (繁體)' },
        { code: 'ar', name: 'العربية' },
        { code: 'hi', name: 'हिन्दी' },
        { code: 'th', name: 'ไทย' },
        { code: 'vi', name: 'Tiếng Việt' },
        { code: 'id', name: 'Bahasa Indonesia' },
        { code: 'ms', name: 'Bahasa Melayu' },
        { code: 'tr', name: 'Türkçe' },
        { code: 'nl', name: 'Nederlands' },
        { code: 'pl', name: 'Polski' },
    ];

    function addStyles() {
        GM_addStyle(`
            .lang-switcher {
                position: fixed;
                top: 10px;
                right: 10px;
                z-index: 9999;
                padding: 5px;
                border-radius: 5px;
                background-color: #f8f9fa;
                border: 1px solid #dadce0;
                font-size: 14px;
                color: #202124;
                transition: opacity 0.3s ease-in-out;
            }
            .lang-switcher:hover {
                opacity: 1 !important;
            }
        `);
    }

    function createLanguageSwitcher() {
        const switcher = document.createElement('select');
        switcher.className = 'lang-switcher';
        switcher.style.opacity = '0.6';

        switcher.add(new Option('Select Language', ''));

        const savedLang = GM_getValue(STORAGE_KEY, '');

        languages.forEach(lang => {
            const option = new Option(lang.name, lang.code);
            if (lang.code === savedLang) {
                option.selected = true;
            }
            switcher.add(option);
        });

        switcher.addEventListener('change', handleLanguageChange);
        document.body.appendChild(switcher);
    }

    function handleLanguageChange(e) {
        const newLang = e.target.value;
        if (newLang) {
            GM_setValue(STORAGE_KEY, newLang);
            applyLanguage(newLang);
        }
    }

    function applyLanguage(lang) {
        const url = new URL(window.location.href);
        url.searchParams.set(LANG_PARAM, lang);
        window.location.href = url.toString();
    }

    function isDomainSupported(hostname) {
        return SUPPORTED_DOMAINS.some(domain => hostname.endsWith(domain));
    }

    function init() {
        if (!isDomainSupported(window.location.hostname)) return;

        const savedLang = GM_getValue(STORAGE_KEY, '');
        const currentLang = new URL(window.location.href).searchParams.get(LANG_PARAM);

        if (savedLang && savedLang !== currentLang) {
            applyLanguage(savedLang);
        } else {
            addStyles();
            createLanguageSwitcher();
        }
    }

    setTimeout(init, 1000);
    })();