使用 Javascript 更改网站语言
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32008125/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Javascript to change website language
提问by Blind Seer
I'm working on a GUI website that can use several languages. The original HTML-files I got to work with were totally static. So if translation was needed I had to parse through alle files, note where some words or terms were, collect them all hand them to the translation department and enter those translations in the new language files.
我正在开发一个可以使用多种语言的 GUI 网站。我使用的原始 HTML 文件完全是静态的。因此,如果需要翻译,我必须解析所有文件,记下某些单词或术语的位置,将它们收集起来交给翻译部门,并将这些翻译输入新的语言文件中。
Since those files were totally static it meant having to translate whole sections several times. Not very effictient.
由于这些文件是完全静态的,这意味着必须多次翻译整个部分。不是很有效。
So now I am working on some kind of dictionary in Javascript, to just exchange the terms in those websites. Mostly it works this way:
所以现在我正在使用 Javascript 编写某种字典,以交换这些网站中的术语。大多数情况下它是这样工作的:
var dicEnglish = {
term 1: "This is the English text"
Ref: "Another English text"
}
var dicFrench = {
term 1: "This is the French text"
Ref: "Another French text"
}
Which contains all the possible content that needs to be changed. Every candidate in the HTML-code gets a class="dicRef" id="l_dicTag_#"
as identifier, which I slice down to the dictionary tag and exchange with the following code:
其中包含所有可能需要更改的内容。HTML 代码中的每个候选者都获得一个class="dicRef" id="l_dicTag_#"
as 标识符,我将其切成字典标记并与以下代码交换:
var imgSrc = "en";
var ActiveDic;
var langSel;
if(window.name){
langSel=window.name;
}
else{langSel="English";
}
function LangChange(){
langClass = document.getElementsByClassName("dicRef");
var i = langClass.length;
var Start, Stop, idSrc, idDic;
var navText;
switch(langSel){
case "French":
langSel="French";
imgSrc = "en";
navText="Anglais";
break;
case "English":
case "Anglais":
default:
langSel="English";
imgSrc = "fr";
navText="French";
break;
}
ActiveDic="dic"+langSel;
window.name=langSel;
while(i--){
idSrc = langClass[i].id;
Start=idSrc.indexOf("_")+1;
Stop=idSrc.lastIndexOf("_");
idDic=idSrc.slice(Start,Stop);
if(window[ActiveDic][idDic]){
document.getElementById(idSrc).innerHTML=window[ActiveDic][idDic];}
else{
document.getElementById(idSrc).innerHTML="N/A";
}
}
if(document.getElementById("imgSel")){
document.getElementById("imgSel").src="../../img/"+imgSrc+".gif";
}
if (document.getElementById("l_SelLang1_1")){
document.getElementById("l_SelLang1_1").innerHTML=navText;
}
}
The problem lies in the uniqueness of the id-tag. Since some terms can occur more than once and some are generated the counter is needed. I'd prefer to ommit the counter, but can't find any other identifier to sort out all target terms and change their content.
问题在于 id-tag 的唯一性。由于某些项可能出现多次,而有些项会生成,因此需要计数器。我更愿意省略计数器,但找不到任何其他标识符来整理所有目标术语并更改其内容。
Since I want to be safe for the future I'd prefer a solution that makes it possible to handle a possible third language. Working with the inner HTML would need to tag the same term several times, once for each language.
因为我想在未来安全,所以我更喜欢一种可以处理可能的第三种语言的解决方案。使用内部 HTML 需要多次标记相同的术语,每种语言一次。
So is there any way to target all terms to be exchanged more efficently and easily, or a better way to do it? I can only work with client-side solutions, so no PHP and so on.
那么有没有什么方法可以更有效、更轻松地交换所有术语,或者有更好的方法呢?我只能使用客户端解决方案,所以没有 PHP 等等。
Thanks in advance and hopefully this wasn't too long to read.
提前致谢,希望阅读时间不会太长。
采纳答案by Andrea Casaccia
You can use data attributes: the fact that "HTML5 attributes are not supported in IE6 and IE7" means that you don't get the getAttribute()
method or the dataset
property for retrieving/accessing them. But you can still retrieve them as explained in this post.
您可以使用数据属性:“IE6 和 IE7 不支持 HTML5 属性”这一事实意味着您无法获取检索/访问它们的getAttribute()
方法或dataset
属性。但你仍然可以检索他们在解释这个职位。
<div id="geoff" data-geoff="geoff">
var geoff = document.getElementById("geoff");
alert(geoff.getAttribute("data-geoff"));
Even better, you can use jQuery .data()to support previous versions of IE.
更好的是,您可以使用 jQuery .data()来支持以前版本的 IE。
Something along these lines should work:
沿着这些路线的东西应该工作:
<div data-translate="translation_key"></div>
$("[data-translate]").each(function(){
var key = $(this).data('translate');
$(this).html(dictionary[key][current_lang] || "N/A");
});
Working example: https://jsfiddle.net/x93oLad8/4/
回答by J Grover
No offense to the other answerers but storing the text in JavaScript or in data attributes is not good for search engines or disabled site visitors and offers no benefits while added unnecessarily complicated code. The best and most simple solution in my opinion is to make use of HTML lang attribute and use JavaScript to show and hide the desired language. This solution also gracefully degrades so if a site visitor has their JavaScript disabled it will still display the content. Here is my solution:
无意冒犯其他回答者,但将文本存储在 JavaScript 或数据属性中对搜索引擎或禁用的站点访问者不利,并且在添加不必要的复杂代码时没有任何好处。我认为最好和最简单的解决方案是利用 HTML lang 属性并使用 JavaScript 来显示和隐藏所需的语言。此解决方案也会优雅地降级,因此如果站点访问者禁用了他们的 JavaScript,它仍将显示内容。这是我的解决方案:
HTML
HTML
<button id="switch-lang">Switch Language</button>
<h1><span lang="en">Hello</span> <span lang="es">Hola</span></h1>
<p lang="en">I really enjoy coding.</p>
<p lang="es">Me gusta mucho la codificación.</p>
jQuery
jQuery
$('[lang="es"]').hide();
$('#switch-lang').click(function() {
$('[lang="es"]').toggle();
$('[lang="en"]').toggle();
});
Then I would recommend adding HTML5 Geolocation to determine which language to show initially based on the users location in the world. I would also use Fontawesome language icon to show users they can switch languages in a way that is understandable by anyone: http://fontawesome.io/icon/language/
然后我建议添加 HTML5 Geolocation 以根据用户在世界上的位置确定最初显示的语言。我还将使用 Fontawesome 语言图标向用户展示他们可以以任何人都能理解的方式切换语言:http: //fontawesome.io/icon/language/
Here is the working code example at CodePen: https://codepen.io/codepajamas/pen/ZejaQz?editors=1010
这是 CodePen 的工作代码示例:https://codepen.io/codepajamas/pen/ZejaQz ?editors =1010
Here is an additional example on code pen using a select menu to change between 3 (or more) languages: https://codepen.io/codepajamas/pen/NjGOMV
以下是使用选择菜单在 3 种(或更多)语言之间切换的代码笔的附加示例:https: //codepen.io/codepajamas/pen/NjGOMV
Updated Full Example with Geolocation and Cookies
使用地理位置和 Cookie 更新完整示例
I kept working on this and created an updated example switching between two languages Chinese and English (if you need more than two languages you would have to hide all languages and show only the one selected instead of using toggle the way I am). This code also detects if an existing cookie is already set for the language using jQuery Cookie. It also checks their geolocation if their browser supports it automatically setting the language to Chinese if they are in either Taiwan or China and defaults to English in all other countries. The code below is commented so you can see what each step is doing and hopefully be able to modify it to suit your needs. Here it is:
我一直在努力解决这个问题,并创建了一个在中文和英文两种语言之间切换的更新示例(如果您需要两种以上的语言,则必须隐藏所有语言并仅显示选定的一种,而不是像我一样使用切换)。此代码还使用 jQuery Cookie 检测是否已经为该语言设置了现有 cookie。如果他们的浏览器支持,它还会检查他们的地理位置,如果他们在台湾或china,它会自动将语言设置为中文,而在所有其他国家/地区默认为英语。下面的代码已被注释,因此您可以查看每个步骤正在执行的操作,并希望能够对其进行修改以满足您的需要。这里是:
HTML
HTML
<button id="switch-lang">Switch Language Icon Here</button>
<h1><span lang="en">Hello</span> <span lang="zh">你好</span></h1>
<p lang="en">I really enjoy coding.</p>
<p lang="zh">我真的很喜歡編碼。</p>
jQueryNote: this requires linking to not only jQuerybut also jQuery Cookie
jQuery注意:这不仅需要链接到jQuery,还需要链接到jQuery Cookie
$(function () {
///// Language Switching (2 languages: English and Chinese). /////
// Initially disable language switching button.
$('#switch-lang').css({'pointer-events':'none',
'cursor':'default'}).attr('disabled','disabled');
function langButtonListen() {
$('#switch-lang').click(function (event) {
event.preventDefault();
$('[lang="zh"]').toggle();
$('[lang="en"]').toggle();
// Switch cookie stored language.
if ($.cookie('lang') === 'en') {
$.cookie('lang', 'zh', { expires: 7 });
} else {
$.cookie('lang', 'en', { expires: 7 });
}
});
// Enable lang switching button.
$('#switch-lang').css({'pointer-events':'auto',
'cursor':'pointer'}).removeAttr('disabled');
}
// Check if language cookie already exists.
if ($.cookie('lang')) {
var lang = $.cookie('lang');
if (lang === 'en') {
$('[lang="zh"]').hide();
langButtonListen();
} else {
$('[lang="en"]').hide();
langButtonListen();
}
} else {
// no cookie set, so detect language based on location.
if ("geolocation" in navigator) {
// geolocation is available
navigator.geolocation.getCurrentPosition(function (position) {
// accepted geolocation so figure out which country
var lat = position.coords.latitude,
lng = position.coords.longitude;
$.getJSON('http://maps.googleapis.com/maps/api/geocode/json?latlng='+lat+','+lng+'&sensor=true', null, function (response) {
var country = response.results[response.results.length-1].formatted_address;
if (country === 'Taiwan' || country === 'China') {
$('[lang="en"]').hide();
$.cookie('lang', 'zh', { expires: 7 });
langButtonListen();
} else {
$('[lang="zh"]').hide();
$.cookie('lang', 'en', { expires: 7 });
langButtonListen();
}
}).fail(function (err) {
console.log('error: '+err);
$('[lang="zh"]').hide();
$.cookie('lang', 'en', { expires: 7 });
langButtonListen();
});
},
function (error) {
if (error.code == error.PERMISSION_DENIED) {
// denied geolocation
$('[lang="zh"]').hide();
$.cookie('lang', 'en', { expires: 7 });
langButtonListen();
} else {
console.log('Unknown error. Defaulting to English!');
$('[lang="zh"]').hide();
$.cookie('lang', 'en', { expires: 7 });
langButtonListen();
}
});
} else {
// geolocation IS NOT available
$('[lang="zh"]').hide();
$.cookie('lang', 'en', { expires: 7 });
langButtonListen());
}
}
});
回答by Andy
One of the ways around this might be to use some sort of client-side templating system for your interface. That way you don't need to unnecessarily load your HTML with a bunch of data attributes detailing the language requirements, but just describe it once in the JavaScript and use a couple of functions to assist with the translation. I've coded up quick example below to show you what I mean.
解决此问题的方法之一可能是为您的界面使用某种客户端模板系统。这样你就不需要用一堆详细说明语言要求的数据属性不必要地加载你的 HTML,而只需在 JavaScript 中描述一次,并使用几个函数来帮助翻译。我在下面编写了快速示例来向您展示我的意思。
Here's the dictionary object. It contains allthe translations by country code. This means you don't need separatedictionaries for each country. This is important because it means we can use this single object structure very easily in out translation function as you'll see in a moment. It also means you can add as many languages and translations as you like.
这是字典对象。它包含按国家/地区代码的所有翻译。这意味着您不需要为每个国家/地区提供单独的词典。这很重要,因为这意味着我们可以很容易地在输出翻译功能中使用这个单一对象结构,正如您稍后将看到的。这也意味着您可以添加任意数量的语言和翻译。
var dict = {
en: {
'Hallo': 'Hallo',
'Goodbye': 'Goodbye',
'castle': 'castle'
},
fr: {
'Hallo': 'Bonjour',
'Goodbye': 'Au revtheitroad',
'castle': 'chateau'
},
de: {
'Hallo': 'Hallo',
'Goodbye': 'Auf Wiedersehen',
'castle': 'schloss'
}
}
This is our country code and it relates directly to the country code key in our dictionary object:
这是我们的国家代码,它直接与我们字典对象中的国家代码键相关:
var lang = 'fr';
The first of our two functions. This takes a template and a language and performs the translation, returning whatever's left (usually some sort of HTML as in our example).
我们的两个功能中的第一个。这需要一个模板和一种语言并执行翻译,返回剩下的任何内容(通常是我们示例中的某种 HTML)。
function applyTemplate(tmpl, lang) {
// find all words within {{word}} a double set of curly braces
// (this format is similar to the handlebars templating engine)
var regex = /\{\{([a-zA-Z])\w+\}\}/g
// for each found word perform the translation and
// remove the curly braces
return tmpl.replace(regex, function (word) {
return translate(dict, lang, word.replace(/[\{\}]/g, ''));
});
}
The translate function takes the dictionary, the language, and a word and returns the translated word. Note that this is much easier with one object containing all the country translations.
translate 函数接受字典、语言和单词并返回翻译后的单词。请注意,使用一个包含所有国家/地区翻译的对象会容易得多。
function translate(dict, lang, word) {
return dict[lang][word];
}
Some HTML. Here is our template (display: none) and the output element. Note the words in the curly braces are the ones to be translated.
一些 HTML。这是我们的模板(显示:无)和输出元素。注意花括号中的词是要翻译的词。
<div class="template"><div>{{Goodbye}}, {{castle}}</div></div>
<div id="translation"><div>
Finally, putting it all together:
最后,把它们放在一起:
// grab the template
var tmpl = document.querySelector('.template').textContent;
var translation = document.querySelector('#translation');
// grab our translated html and add it to the output element
var html = applyTemplate(tmpl, lang);
translation.insertAdjacentHTML('afterbegin', html);
Now, obviously you don't have to use this method (there are dozens of JS templating engines out there), but templating is particularlyuseful for sites that need to use multiple languages. Many do this on the back end but, as you can see, it can be easily done client-side too.
现在,显然您不必使用这种方法(那里有数十种 JS 模板引擎),但是模板对于需要使用多种语言的站点特别有用。许多人在后端执行此操作,但正如您所见,它也可以在客户端轻松完成。
Hope this was useful and given you a couple of different ideas on how you might approach your solution.
希望这是有用的,并就如何处理解决方案为您提供一些不同的想法。
回答by Priyabrat Rath
<script type="text/javascript">
// Load the Google Transliteration API google.load("elements", "1", { packages: "transliteration" });
// 加载 Google Transliteration API google.load("elements", "1", { packages: "transliteration" });
var transliterationControl;
function onLoad() {
var options = {
sourceLanguage: 'en',
destinationLanguage: ['hi','or','bn','ta','te'],
transliterationEnabled: true,
shortcutKey: 'ctrl+g'
};
// Create an instance on TransliterationControl with the required
// options.
transliterationControl =
new google.elements.transliteration.TransliterationControl(options);
// Enable transliteration in the textfields with the given ids.
var ids = [ "transl1", "transl2" ];
transliterationControl.makeTransliteratable(ids);
// Add the STATE_CHANGED event handler to correcly maintain the state
// of the checkbox.
transliterationControl.addEventListener(
google.elements.transliteration.TransliterationControl.EventType.STATE_CHANGED,
transliterateStateChangeHandler);
// Add the SERVER_UNREACHABLE event handler to display an error message
// if unable to reach the server.
transliterationControl.addEventListener(
google.elements.transliteration.TransliterationControl.EventType.SERVER_UNREACHABLE,
serverUnreachableHandler);
// Add the SERVER_REACHABLE event handler to remove the error message
// once the server becomes reachable.
transliterationControl.addEventListener(
google.elements.transliteration.TransliterationControl.EventType.SERVER_REACHABLE,
serverReachableHandler);
// Set the checkbox to the correct state.
document.getElementById('checkboxId').checked =
transliterationControl.isTransliterationEnabled();
// Populate the language dropdown
var destinationLanguage =
transliterationControl.getLanguagePair().destinationLanguage;
var languageSelect = document.getElementById('languageDropDown');
var supportedDestinationLanguages =
google.elements.transliteration.getDestinationLanguages(
google.elements.transliteration.LanguageCode.ENGLISH);
for (var lang in supportedDestinationLanguages) {
var opt = document.createElement('option');
opt.text = lang;
if (lang=="TAMIL" || lang=="TELUGU" || lang=="HINDI" || lang=="ORIYA" || lang=="BENGALI"){
opt.value = supportedDestinationLanguages[lang];
if (destinationLanguage == opt.value) {
opt.selected = true;
}
try {
languageSelect.add(opt, null);
} catch (ex) {
languageSelect.add(opt);
}
}//End of if
}
}
// Handler for STATE_CHANGED event which makes sure checkbox status
// reflects the transliteration enabled or disabled status.
function transliterateStateChangeHandler(e) {
document.getElementById('checkboxId').checked = e.transliterationEnabled;
}
// Handler for checkbox's click event. Calls toggleTransliteration to toggle
// the transliteration state.
function checkboxClickHandler() {
transliterationControl.toggleTransliteration();
}
// Handler for dropdown option change event. Calls setLanguagePair to
// set the new language.
function languageChangeHandler() {
var dropdown = document.getElementById('languageDropDown');
transliterationControl.setLanguagePair(
google.elements.transliteration.LanguageCode.ENGLISH,
dropdown.options[dropdown.selectedIndex].value);
}
// SERVER_UNREACHABLE event handler which displays the error message.
function serverUnreachableHandler(e) {
document.getElementById("errorDiv").innerHTML =
"Transliteration Server unreachable";
}
// SERVER_UNREACHABLE event handler which clears the error message.
function serverReachableHandler(e) {
document.getElementById("errorDiv").innerHTML = "";
}
google.setOnLoadCallback(onLoad);