Reputation: 474
I am using the jQuery multilanguage solution from https://github.com/coderkan/multi-language-jquery to add translation to a project I am working on which is working like it should, but I have an input field with a placeholder I also need to translate, but the "tools" in the JS does not give me a way out of the box to do so since I cannot place a <span>
or similar into the placeholder=""
attribute, so I need to find a solution on how I can do this.
The code:
What is "normally" used to add the translation in the HTML:
<span name="translate" caption="Need_Help"></span>
The INPUT field with placeholder ("Search.." is to be translated):
<input class="form-control" id="SearchEmployee" name="translate" caption="Search_Employee" type="text" value="" placeholder="Search..">
The jQuery:
function getLangResources() {
// Define arrays how many language you want to translate
var da = new Array();
var en = new Array();
da['Need_Help'] = "Brug for hjælp?";
en['Need_Help'] = "Need help?";
// Added new array defined arrays.
var resources = new Array();
resources['da'] = da;
resources['en'] = en;
return resources;
}
function changeLanguage(lng) {
var resources = getLangResources()[lng];
$("h1[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("h2[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("h3[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("span[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("p[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("button[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
// This I have tried to deal with placeholder
$("input[placeholder][name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
}
$(function() {
// Default Language
changeLanguage("da");
$("#da_button").click(function() {
changeLanguage("da");
});
$("#eng_button").click(function() {
changeLanguage("en");
});
});
Upvotes: 0
Views: 388
Reputation: 338158
I would start with a rework of your code, you're already not headed into a good direction.
Let's start with your getLangResources()
function. The data structure it returns is basically a nested object, so let's skip all those tedious (and ill-applied) arrays:
function getLangResources() {
return {
Need_Help: {
da: 'Brug for hjælp?',
en: 'Need help?'
}
}
}
I suppose at some point this might return data from an HTTP request that fetches some JSON file, but for now let's keep it at returning a constant value.
const resources = getLangResources();
Next, your changeLanguage()
function. It shows clear signs of copy-paste programming, so let's get rid of those first. Assume that each translatable element on your page has a CSS class called translate
:
function changeLanguage(lng) {
$(".translate").each(function () {
$(this).text(resources[this.caption][lng]);
});
}
This is better, but it still has drawbacks.
caption
attribute, and those are not standard HTML.So let's go one step further and address those
data
attribute that contains the resource ID: data-resource="Need_Help"
data-resource-target="text"
.This would lead us to:
function changeLanguage(lng) {
$(".translate").each(function () {
var resourceId = $(this).data("resource");
var resourceTarget = $(this).data("resource-target");
$(this)[resourceTarget](resources[resourceId][lng]);
});
}
That's better, since it allows us to choose e.g. html
or text
as the targets, which would enable basic HTML formatting such as bold in resource strings.
But it's still rather rigid
So let's scrap that as well. What if we made up a format that allows defining multiple properties at once? I could imagine a list of id-target pairs could work:
data-lng="<resouce-id>:<resource-target>,<resouce-id>:<resource-target>,..."
We could name the targets according to HTML properties...
<a href="..." class="translate" data-lng="Need_Help:textContent,Further_Information:title"></a>
...and set them directly on the element itself, instead of going through jQuery.
function changeLanguage(lng) {
$(".translate").each(function () {
var lng = $(this).data("lng");
for (let pair of lng.split(',')) {
let [resourceId, target] of pair.split(':');
this[target] = resources[resourceId][lng];
}
});
}
Now you can target the placeholder
just as easily as everything else.
Going from there you could go on and define convenience shorthands, things like
textContent
: data-lng="Need_Help"
textContent
, such as .
: data-lng="Need_Help:.,Further_Information:title"
It's up to you, whatever you find practical.
Upvotes: 1
Reputation: 9839
You can fix it like this. Try running the snippet, the code is runnable. Your problem is that your code uses the .text(...)
function which sets the inner text, that is the contents between the opening and closening html tags, for a html emlement. To set a attribute of an html element, which placeholder is, you need to use the .attr(...)
or .prop(...)
functions.
function getLangResources() {
// Define arrays how many language you want to translate
var da = new Array();
var en = new Array();
da['Need_Help'] = "Brug for hjælp?";
en['Need_Help'] = "Need help?";
da['Search_Employee'] = "søg efter en medarbejder";
en['Search_Employee'] = "Search employee";
// Added new array defined arrays.
var resources = new Array();
resources['da'] = da;
resources['en'] = en;
return resources;
}
function changeLanguage(lng) {
var resources = getLangResources()[lng];
$("h1[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("h2[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("h3[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("span[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("p[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("button[name='translate']").each(function(i, elt) {
$(elt).text(resources[$(elt).attr("caption")]);
});
$("input[placeholder][name='translate']").each(function(i, elt) {
$(elt).attr("placeholder", resources[$(elt).attr("caption")]);
});
}
$(function() {
// Default Language
changeLanguage("da");
$("#da_button").click(function() {
changeLanguage("da");
});
$("#eng_button").click(function() {
changeLanguage("en");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span name="translate" caption="Need_Help" /></span>
<input class="form-control" id="SearchEmployee" name="translate" caption="Search_Employee" type="text" value="" placeholder="Search.." />
Upvotes: 1