nuxt-google-translate
Version:
A simple Nuxt module that integrates the Google Translate widget into your Nuxt.js application, allowing seamless multilingual support without requiring an API key.
106 lines (105 loc) • 3.75 kB
JavaScript
import { ref, readonly } from "vue";
import { defineNuxtPlugin, useRuntimeConfig } from "#app";
export default defineNuxtPlugin((nuxtApp) => {
const config = useRuntimeConfig();
const options = config.public.googleTranslate;
const defaultLanguage = options?.defaultLanguage ?? "en";
const supportedLanguages = options?.supportedLanguages ?? ["en"];
const activeLanguage = ref(defaultLanguage);
if (import.meta.client) {
const cookieLang = document.cookie.split("; ").find((row) => row.startsWith("googtrans="))?.split("=")[1]?.split("/")[2];
if (cookieLang && supportedLanguages.includes(cookieLang)) {
activeLanguage.value = cookieLang;
}
}
const isLoaded = ref(false);
const deleteGoogtransCookie = () => {
const cookieName = "googtrans";
const expiry = "expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
document.cookie = `${cookieName}=; ${expiry}`;
document.cookie = `${cookieName}=; ${expiry} domain=${window.location.hostname};`;
const baseDomain = window.location.hostname.split(".").slice(-2).join(".");
if (baseDomain !== window.location.hostname) {
document.cookie = `${cookieName}=; ${expiry} domain=.${baseDomain};`;
}
};
const setLanguage = (lang) => {
if (!supportedLanguages.includes(lang)) {
console.warn(`[nuxt-google-translate] Unsupported language: ${lang}.`);
return;
}
if (lang === defaultLanguage) {
deleteGoogtransCookie();
if (activeLanguage.value !== defaultLanguage) {
location.reload();
}
activeLanguage.value = defaultLanguage;
return;
}
if (lang !== activeLanguage.value) {
activeLanguage.value = lang;
updateGoogleTranslate(lang);
if (import.meta.client) {
document.cookie = `googtrans=/en/${lang};path=/;`;
}
}
};
const updateGoogleTranslate = (lang) => {
if (!import.meta.client || !isLoaded.value) return;
const select = document.querySelector(".goog-te-combo");
if (select) {
select.value = lang;
select.dispatchEvent(new Event("change"));
}
};
const initializeGoogleTranslate = () => {
if (!window.google?.translate?.TranslateElement) return;
new window.google.translate.TranslateElement(
{
pageLanguage: defaultLanguage,
includedLanguages: supportedLanguages.join(","),
layout: window.google.translate.TranslateElement.InlineLayout.VERTICAL,
autoDisplay: false
},
"nuxt_translate_element"
);
isLoaded.value = true;
updateGoogleTranslate(activeLanguage.value);
};
const loadGoogleTranslate = () => {
if (!import.meta.client || isLoaded.value) return;
if (document.querySelector("#google-translate-script")) return;
window.googleTranslateElementInit = initializeGoogleTranslate;
if (window.google?.translate?.TranslateElement) {
initializeGoogleTranslate();
return;
}
const script = document.createElement("script");
script.id = "google-translate-script";
script.src = "//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit";
script.async = true;
script.defer = true;
script.onload = () => {
initializeGoogleTranslate();
};
script.onerror = () => {
console.error("[nuxt-google-translate] Failed to load Google Translate script.");
};
document.body.appendChild(script);
};
if (import.meta.client) {
nuxtApp.hook("app:mounted", () => {
loadGoogleTranslate();
});
}
return {
provide: {
googleTranslate: {
activeLanguage: readonly(activeLanguage),
supportedLanguages: readonly(supportedLanguages),
setLanguage,
isLoaded: readonly(isLoaded)
}
}
};
});