问题
一般没有适配国际化的页面 我们会使用谷歌翻译插件进行翻译。
但由于使用浏览器中的谷歌翻译插件 会导致dom的结构发生改变,从而导致 vue react与dom操作绑定关系失效!这样就无法触发跳转路由等操作。
下面的方法可以使得我们即使用谷歌翻译 又不会导致dom结构发生改变 兼容vue react(把vue代码改写一下)框架。
效果
hhh-google-translate
注意
而且选择语言时,切换语言最好先切换为源语言,再切换翻译语言,不然谷歌翻译会翻译错乱。
代码
hhh-google-translate 组件
这是我参考
利用Google翻译实现网站国际化——js插件
v-google-translate 写的。
目前有两个版本 切换组件的index.vue。 其中( 翻译input提示内容 无法翻译),需要在public 的添加css及js 已放置在google-translate-vue中,可下载使用。
google-translate内容图片
demo 代码 如下
//hhh-google-translate 组件
<template>
<div>
<div id="google_translate_element"></div>
</div>
</template>
<script>
// import googleElement from "./google-element";
export default {
name: "hhh-google-translate",
props: {
// 语言列表
languages: {
type: Array,
default() {
// 遵循 ISO 639-1 标准,俩位的code
// 参考:https://zh.wikipedia.org/wiki/ISO_639-1
return [
{
code: "en",
name: "English",
cname: "英语",
ename: "English",
},
{
code: "af",
name: "Afrikaans",
cname: "南非语",
ename: "Afrikaans",
},
{
code: "sq",
name: "Gjuha shqipe",
cname: "阿尔巴尼亚语",
ename: "Albanian",
},
{
code: "ar",
name: "العربية",
cname: "阿拉伯语",
ename: "Arabic",
},
{
code: "hy",
name: "Հայերեն",
cname: "亚美尼亚语",
ename: "Armenian",
},
{
code: "az",
name: "Азәрбајҹан дили",
cname: "阿塞拜疆语",
ename: "Azerbaijani",
},
{
code: "eu",
name: "Euskara",
cname: "巴斯克语",
ename: "Basque",
},
{
code: "be",
name: "беларуская мова",
cname: "白俄罗斯语",
ename: "Belarusian",
},
{
code: "bg",
name: "български език",
cname: "保加利亚语",
ename: "Bulgarian",
},
{
code: "ca",
name: "Català",
cname: "加泰罗尼亚语",
ename: "Catalan",
},
{
code: "zh-CN",
name: "Chinese (Simplified)",
cname: "中文 (简体)",
ename: "Chinese (Simplified)",
},
{
code: "zh-TW",
name: "Chinese (Traditional)",
cname: "中文 (繁体)",
ename: "Chinese (Traditional)",
},
{
code: "hr",
name: "Српскохрватски језик",
cname: "克罗地亚语",
ename: "Croatian",
},
{
code: "cs",
name: "čeština",
cname: "捷克语",
ename: "Czech",
},
{
code: "da",
name: "Danmark",
cname: "丹麦语",
ename: "Danish",
},
{
code: "nl",
name: "Nederlands",
cname: "荷兰语",
ename: "Dutch",
},
{
code: "et",
name: "eesti keel",
cname: "爱沙尼亚语",
ename: "Estonian",
},
{
code: "tl",
name: "Filipino",
cname: "菲律宾语",
ename: "Filipino",
},
{
code: "fi",
name: "Finnish",
cname: "芬兰语",
ename: "Finnish",
},
{
code: "fr",
name: "Français",
cname: "法语",
ename: "French",
},
{
code: "de",
name: "Deutsch",
cname: "德语",
ename: "German",
},
{
code: "el",
name: "Ελληνικά",
cname: "希腊语",
ename: "Greek",
},
{
code: "hu",
name: "magyar",
cname: "匈牙利语",
ename: "Hungarian",
},
{
code: "id",
name: "Indonesia",
cname: "印度尼西亚语",
ename: "Indonesian",
},
{
code: "ga",
name: "Irish",
cname: "爱尔兰语",
ename: "Irish",
},
{
code: "it",
name: "Italiano",
cname: "意大利语",
ename: "Italian",
},
{
code: "ja",
name: "にほんご",
cname: "日语",
ename: "Japanese",
},
{
code: "ko",
name: "한국어",
cname: "韩语",
ename: "Korean",
},
{
code: "lt",
name: "lietuvių kalba",
cname: "立陶宛语",
ename: "Lithuanian",
},
{
code: "ms",
name: "Malay",
cname: "马来西亚语",
ename: "Malay",
},
{
code: "no",
name: "norsk",
cname: "挪威语",
ename: "Norwegian",
},
{
code: "pl",
name: "Polski",
cname: "波兰语",
ename: "Polish",
},
{
code: "pt",
name: "Português",
cname: "葡萄牙语",
ename: "Portuguese",
},
{
code: "ro",
name: "limba română",
cname: "罗马尼亚语",
ename: "Romanian",
},
{
code: "ru",
name: "Русский",
cname: "俄语",
ename: "Russian",
},
{
code: "es",
name: "Español",
cname: "西班牙语",
ename: "Spanish",
},
{
code: "sv",
name: "Swedish",
cname: "瑞典语",
ename: "Swedish",
},
{
code: "th",
name: "ภาษาไทย",
cname: "泰语",
ename: "Thai",
},
{
code: "tr",
name: "Turkish",
cname: "土耳其语",
ename: "Turkish",
},
{
code: "uk",
name: "українська мова",
cname: "乌克兰语",
ename: "Ukrainian",
},
];
},
},
//默认页面源语言 code
defaultPageLanguageCode: {
type: String,
default: "auto",//zh-CN 简体中文
},
},
data() {
return {};
},
created() {},
computed: {
includedLanguages() {
if (this.languages && this.languages.length) {
let languagesList =
this.languages.map((item) => {
return item.code;
}) || [];
return languagesList.join(",");
}
return "";
},
},
mounted() {
window.googleTranslateElementInit = () => {
//记录 谷歌翻译是否已经初始化
window.hhhTransLateInit = true;
console.log("window.google.translate", window.google.translate);
// new window.google.translate.TranslateElement({ pageLanguage: this.defaultPageLanguageCode, autoDisplay: false }, "google_translate_element");
new window.google.translate.TranslateElement(
{ pageLanguage: this.defaultPageLanguageCode, includedLanguages: this.includedLanguages, autoDisplay: true, layout: google.translate.TranslateElement.InlineLayout.SIMPLE },
"google_translate_element"
);
};
console.log("window.hhhTransLateInit", window.hhhTransLateInit);
//如果谷歌翻译已经初始化
if (window.hhhTransLateInit) {
// 重新渲染到 google_translate_element 上
_loadJs("https:\/\/translate.googleapis.com\/_\/translate_http\/_\/js\/k\x3dtranslate_http.tr.zh_CN.QLOO522nbPo.O\/d\x3d1\/exm\x3del_conf\/ed\x3d1\/rs\x3dAN8SPfrH_TG1Vgc2X6ozBFVgRhW67pLkSQ\/m\x3del_main");
}
// if (window.google.translate.TranslateElement) {
// new window.google.translate.TranslateElement({ includedLanguages: this.includedLanguages, autoDisplay: false, layout: google.translate.TranslateElement.InlineLayout.SIMPLE }, "google_translate_element");
// }
this.dynamicLoadJs("//translate.google.cn/translate_a/element.js?cb=googleTranslateElementInit");
},
methods: {
// 动态加载js文件
dynamicLoadJs(jsUrl, fn = () => {}, errorCallBack = () => {}, jsId = "") {
const scriptList = document.querySelectorAll("script");
console.log("scriptList", scriptList);
const isLoad = [...scriptList].find((item) => {
return item.getAttribute("src") == jsUrl;
});
console.log("isLoad", isLoad);
if (!isLoad) {
const _doc = document.querySelector("body");
const script = document.createElement("script");
script.onload = script.onreadystatechange = function() {
console.log("this.readyState", this.readyState);
// 加载成功
if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") {
fn && fn();
}
// 加载失败
if (!this.readyState || ((this.readyState === "loaded" || this.readyState === "complete") && !window["_DumpException"])) {
errorCallBack && errorCallBack();
}
script.onload = script.onreadystatechange = null;
};
script.setAttribute("type", "text/javascript");
script.setAttribute("src", jsUrl);
jsId && script.setAttribute("id", jsId);
_doc.appendChild(script);
}
},
},
};
</script>
<style>
body {
top: 0 !important;
}
.skiptranslate iframe {
display: none;
}
/* 去除查看原文 */
#goog-gt-tt {
display: none !important;
}
/* 去除选择文字高亮 */
.goog-text-highlight{
background-color: inherit !important;
box-shadow: none !important;
}
#google_translate_element {
/* width: 150px; */
/* display: flex; */
/* position: absolute;
top: 0;
right: 0;
z-index: 2000;
opacity: 0.7; */
}
#google_translate_element .goog-te-gadget {
width: 100%;
height: 100%;
}
#google_translate_element .goog-te-gadget .goog-te-gadget-simple {
background-color: transparent;
border: none;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
/* 去除重复的内容 */
/* #google_translate_element .goog-te-gadget .goog-te-gadget-simple span:nth-of-type(n + 2) {
display: none;
}
#google_translate_element .goog-te-gadget .goog-te-gadget-simple img:nth-of-type(n + 2) {
display: none;
} */
/* #google_translate_element .goog-te-menu-value:first-child {
display: inline-block;
} */
#google_translate_element .goog-te-menu-value :nth-child(n + 2) {
display: none;
}
#google_translate_element .goog-te-menu-value img {
width: 1em !important;
height: 1em !important;
}
/* .skiptranslate {
display: none !important;
} */
</style>
使用
// 如果想全局先引入 谷歌的element.js文件 请在 index.html 添加以下script
//index.html
<div id="app"></div>
<script async src="//translate.google.cn/translate_a/element.js?cb=googleTranslateElementInit"></script>
//使用
<hhh-google-translate />
v-google-translate 组件
yarn add v-google-translate
npm i v-google-translate
使用
// main.js
import vGoogleTranslate from "v-google-translate";
Vue.use(vGoogleTranslate);
// xxx.vue
<template>
<div>
<v-google-translate />
<div>
</template>
不过使用 npm 安装 可能会报错
gyp ERR! find Python
gyp ERR! find VS msvs_version not set from command line or npm config
缺少python 环境 缺少c++环境
如果报错建议去github下载源码
具体参考 v-google-translate
这两个组件都可以通过 添加 notranslate 类名,这样谷歌翻译将不会翻译该元素内文字
<a :href="href" class="navbar-brand notranslate">不翻译的字</a>