FOERBICO-metadata-form/metadata-generator.html
2022-03-09 09:18:46 +01:00

660 lines
26 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<title>OER Metadaten Formular</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.1/js/bootstrap-select.min.js"></script> -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.9/dist/css/bootstrap-select.min.css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"/>
<!-- Latest compiled and minified JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.9/dist/js/bootstrap-select.min.js"></script>
<!-- (Optional) Latest compiled and minified JavaScript translation files -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.9/dist/js/i18n/defaults-de_DE.min.js"></script>
<script src="https://unpkg.com/i18next/dist/umd/i18next.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js"></script>
<style>
.btn-primary {
background-color: #0A1F40;
border: 0;
}
.main {
margin-top: 40px;
padding: 0 20px;
margin-bottom: 120px;
}
.input-dropdown {
background: #F1F6DF;
color: #0A1F40;
}
</style>
</head>
<body>
<nav class="navbar navbar-light bg-light">
<div class="navbar-brand">
<img src="logo.svg" height="50" width="116" alt="LOGO">
</div>
<form class="form-inline ml-auto mr-3">
<button class="btn" type="button" data-toggle="modal" data-target="#importModal">Import</button>
</form>
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarLanguageDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span id="selectedLanguageLabel">DE</span>
</a>
<div class="dropdown-menu position-absolute dropdown-menu-right" aria-labelledby="navbarLanguageDropdown">
<a class="dropdown-item" onclick="changeLanguage('en')">English</a>
<a class="dropdown-item" onclick="changeLanguage('de')">Deutsch</a>
</div>
</li>
</ul>
</nav>
<!-- Modal -->
<div class="modal fade" id="importModal" tabindex="-1" role="dialog" aria-labelledby="importModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Import</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<textarea rows="15" class="form-control" id="importData" placeholder="Daten" data-i18n-placeholder="LABEL_IMPORT_DATA_PLACEHOLDER"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" data-i18n="LABEL_CLOSE">Schließen</button>
<button type="button" class="btn btn-primary" data-i18n="LABEL_IMPORT" onclick="importData()">Import</button>
</div>
</div>
</div>
</div>
<div class="container main">
<h2 style="margin-bottom:40px;" data-i18n="FORM_HEADING">OER Metadaten Formular</h2>
<form class="was-validated">
<div class="form-group row">
<label for="inputStatus" class="col-sm-2 col-form-label" data-i18n="LABEL_STATUS">Status</label>
<div class="col-sm-10">
<select class="custom-select" id="inputStatus" required>
<option value="Draft" data-i18n="LABEL_STATUS_DRAFT" selected>Entwurf</option>
<option value="Incomplete" data-i18n="LABEL_STATUS_INCOMPLETE">Unvollständig</option>
<option value="Published" data-i18n="LABEL_STATUS_PUBLISHED">Veröffentlicht</option>
</select>
<div class="valid-feedback"></div>
<div class="invalid-feedback" data-i18n="LABEL_MANDATORY_FIELD">Pflichtfeld</div>
</div>
</div>
<div class="form-group row">
<label for="inputUrl" class="col-sm-2 col-form-label" data-i18n="LABEL_URL">URL</label>
<div class="col-sm-10">
<input type="url" class="form-control" id="inputUrl" placeholder="URL"
data-i18n-placeholder="LABEL_URL" value="" required>
<div class="valid-feedback"></div>
<div class="invalid-feedback" data-i18n="LABEL_MANDATORY_FIELD">Pflichtfeld</div>
</div>
</div>
<div class="form-group row">
<label for="inputTitle" class="col-sm-2 col-form-label" data-i18n="LABEL_TITLE">Titel</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="inputTitle" placeholder="Titel"
data-i18n-placeholder="LABEL_TITLE" value="" required>
<div class="valid-feedback"></div>
<div class="invalid-feedback" data-i18n="LABEL_MANDATORY_FIELD">Pflichtfeld</div>
</div>
</div>
<div class="form-group row">
<label for="inputDescription" class="col-sm-2 col-form-label"
data-i18n="LABEL_DESCRIPTION">Beschreibung</label>
<div class="col-sm-10">
<textarea class="form-control" id="inputDescription" placeholder="Beschreibung" data-i18n-placeholder="LABEL_DESCRIPTION"></textarea>
</div>
</div>
<div class="form-group row">
<label for="inputTags" class="col-sm-2 col-form-label" data-i18n="LABEL_KEYWORDS">Schlagworte</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="inputTags" placeholder="Komma getrennte Liste von Schlagworten"
data-i18n-placeholder="LABEL_KEYWORDS_PLACEHOLDER" value="">
</div>
</div>
<div class="form-group row">
<label for="inputResourceType" class="col-sm-2 col-form-label" data-i18n="LABEL_LEARNINGRESOURCETYPE">Materialart</label>
<div class="col-sm-10">
<select data-style="input-dropdown" data-width="100%" class="selectpicker" id="inputResourceType" data-i18n-title="LABEL_LEARNINGRESOURCETYPE_CHOOSE" required multiple>
</select>
<div class="valid-feedback"></div>
<div class="invalid-feedback" data-i18n="LABEL_MANDATORY_FIELD">Pflichtfeld</div>
</div>
</div>
<div class="form-group row">
<label for="creator-list" class="col-sm-2 col-form-label" data-i18n="LABEL_CREATOR">Autor</label>
<div class="col-sm-10 form-row">
<ul class="list-group col" id="creator-list">
<li class="list-group-item">
<button type="button" onclick="addCreator()" class="btn btn-primary"><i class="fa fa-plus"></i> <span
data-i18n="LABEL_CREATOR_ADD">Autor hinzufügen</span></button>
</li>
</ul>
</div>
</div>
<div class="form-group row">
<label for="inputLanguage" class="col-sm-2 col-form-label" data-i18n="LABEL_LANGUAGE">Sprache</label>
<div class="col-sm-10">
<select data-style="input-dropdown" data-width="100%" class="selectpicker" id="inputLanguage" data-i18n-title="LABEL_CHOOSE" required multiple>
</select>
<div class="valid-feedback"></div>
<div class="invalid-feedback">Pflichtfeld</div>
</div>
</div>
<div class="form-group row">
<label for="choicesLicense" class="col-sm-2 col-form-label" data-i18n="LABEL_LICENSE">Lizenz</label>
<div class="col-sm-7" id="choicesLicense">
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" onclick="chooseLicense()" class="form-check-input" id="inputLicenseBY" value="BY"
checked>
<span data-i18n="LABEL_LICENSE_CHECKBOX_BY">darf ohne Namensnennung verwendet werden</span>
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" onclick="chooseLicense()" class="form-check-input" id="inputLicenseSA" value="SA"
checked>
<span data-i18n="LABEL_LICENSE_CHECKBOX_SA">darf unter anderer Lizenz veröffentlicht werden</span>
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" onclick="chooseLicense()" class="form-check-input" id="inputLicenseND" value="ND"
checked>
<span data-i18n="LABEL_LICENSE_CHECKBOX_ND">darf verändert werden</span>
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" onclick="chooseLicense()" class="form-check-input" id="inputLicenseNC" value="NC"
checked>
<span data-i18n="LABEL_LICENSE_CHECKBOX_NC">darf kommerziell genutzt werden</span>
<input type="hidden" id="licenseUrl"
value="https://creativecommons.org/share-your-work/public-domain/cc0/">
</label>
</div>
</div>
<div class="col-sm-3">
<label for="choicesLicense" id="choosenLicense" class="col-form-label">CC-0</label>
</div>
</div>
<div class="form-group row">
<label for="inputSourceOrganization" class="col-sm-2 col-form-label" data-i18n="LABEL_ORGANIZATION">Institution</label>
<div class="col-sm-10">
<select data-style="input-dropdown" data-width="100%" class="selectpicker" id="inputSourceOrganization" data-live-search="true">
<option value="" data-i18n="LABEL_CHOOSE" selected>Wähle ...</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="inputSubjectOf" class="col-sm-2 col-form-label" data-i18n="LABEL_SUBJECT">Fach</label>
<div class="col-sm-10">
<select data-style="input-dropdown" data-width="100%" class="selectpicker" id="inputSubjectOf" data-live-search="true" data-i18n-title="LABEL_CHOOSE" multiple>
</select>
</div>
</div>
<div class="form-group row">
<label for="inputImage" class="col-sm-2 col-form-label" data-i18n="LABEL_IMAGE_URL">Vorschaubild URL</label>
<div class="col-sm-10">
<input type="url" class="form-control" id="inputImage" placeholder="Vorschaubild URL" data-i18n-placeholder="LABEL_IMAGE_URL" value="">
</div>
</div>
<button type="button" onclick="generate()" class="btn btn-primary"><i class="fa fa-arrow-down"></i> <span data-i18n="LABEL_GENERATE">Generieren</span>
</button>
<div class="form-group">
<label for="comment" data-i18n="LABEL_YAML_METADATA">YAML Metadaten</label>
<textarea class="form-control" rows="15" id="comment"></textarea>
</div>
</form>
</div>
<footer class="bg-light text-center">
<div class="text-center p-3">
GitLab:
<a class="text-dark" href="https://gitlab.com/oersi/metadata-form">https://gitlab.com/oersi/metadata-form</a>
</div>
</footer>
</div>
<script>
init();
async function init() {
await loadVocabs();
await i18nLoader();
chooseLicense();
addCreator();
}
function loadVocabs() {
$(document).ready(function () {
$.getJSON("vocabs/hcrt.json", function (result) {
$.each(result, function (i, item) {
$("#inputResourceType").append('<option value="' + item + '" data-i18n="' + item + '"></option>');
});
});
$.getJSON("vocabs/language.json", function (result) {
$.each(result, function (i, item) {
$("#inputLanguage").append('<option value="' + item + '" data-i18n="' + item + '"></option>');
});
});
$.getJSON("vocabs/organizations.json", function (result) {
$.each(result, function (i, item) {
$("#inputSourceOrganization").append('<option value="' + item["ror"] + '">' + item["label"] + '</option>');
});
});
$.getJSON("vocabs/subject.json", function (result) {
$.each(result, function (i, item) {
$("#inputSubjectOf").append('<option value="' + item + '" data-i18n="' + item + '"></option>');
});
});
});
}
var licenses = [
{
shortName: "CC-0",
color: "green",
name: "Public Domain",
url: "https://creativecommons.org/publicdomain/zero/1.0/deed.de",
icon: ""
},
{
shortName: "CC BY",
color: "green",
name: "Namensnennung 4.0 International",
url: "https://creativecommons.org/licenses/by/4.0/deed.de",
icon: ""
},
{
shortName: "CC BY-SA",
color: "yellow",
name: "Namensnennung - Weitergabe unter gleichen Bedingungen 4.0 International",
url: "https://creativecommons.org/licenses/by-sa/4.0/deed.de",
icon: ""
},
{
shortName: "CC BY-ND",
color: "orange",
name: "Namensnennung - Keine Bearbeitungen 4.0 International",
url: "https://creativecommons.org/licenses/by-nd/4.0/deed.de",
icon: ""
},
{
shortName: "CC BY-NC",
color: "red",
name: "Namensnennung-Nicht kommerziell 4.0 International",
url: "https://creativecommons.org/licenses/by-nc/4.0/deed.de",
icon: ""
},
{
shortName: "CC BY-SA-NC",
color: "red",
name: "Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 4.0 International",
url: "https://creativecommons.org/licenses/by-nc-sa/4.0/deed.de",
icon: ""
},
{
shortName: "CC BY-ND-NC",
color: "red",
name: "Namensnennung - Nicht kommerziell - Keine Bearbeitungen 4.0 International",
url: "https://creativecommons.org/licenses/by-nc-nd/4.0/deed.de",
icon: ""
}
];
function chooseLicense() {
const by = document.getElementById("inputLicenseBY")
const sa = document.getElementById("inputLicenseSA")
const nd = document.getElementById("inputLicenseND")
const nc = document.getElementById("inputLicenseNC")
let licenseShortName = "CC"
if (by.checked === false) {
licenseShortName += " " + by.value
}
if (sa.checked === false) {
licenseShortName += "-" + sa.value
}
if (nd.checked === false) {
licenseShortName += "-" + nd.value
}
if (nc.checked === false) {
licenseShortName += "-" + nc.value
}
if (licenseShortName === "CC") {
licenseShortName = "CC-0"
}
document.getElementById("choosenLicense").innerText = licenseShortName
let color = ""
switch (licenseShortName) {
case "CC-0":
color = "green"
by.disabled = false;
sa.disabled = true;
nd.disabled = true;
nc.disabled = true;
break;
case "CC BY":
color = "green"
by.disabled = false;
sa.disabled = false;
nd.disabled = false;
nc.disabled = false;
break;
case "CC BY-SA":
color = "orange"
by.disabled = true;
sa.disabled = false;
nd.disabled = true;
nc.disabled = false;
break;
case "CC BY-ND":
color = "orange"
by.disabled = true;
sa.disabled = true;
nd.disabled = false;
nc.disabled = false;
break;
case "CC BY-NC":
color = "red"
by.disabled = true;
sa.disabled = false;
nd.disabled = false;
nc.disabled = false;
break;
case "CC BY-SA-NC":
color = "red"
by.disabled = true;
sa.disabled = false;
nd.disabled = true;
nc.disabled = false;
break;
case "CC BY-ND-NC":
color = "red"
by.disabled = true;
sa.disabled = true;
nd.disabled = false;
nc.disabled = false;
break;
default:
color = "grey"
document.getElementById("choosenLicense").innerText = i18next.t("LABEL_INVALID_LICENSE")
document.getElementById("licenseUrl").value = ""
by.disabled = false;
sa.disabled = false;
nd.disabled = false;
nc.disabled = false;
}
document.getElementById("choosenLicense").style.color = color
for (x in licenses) {
if (licenses[x].shortName === licenseShortName) {
document.getElementById("licenseUrl").value = licenses[x].url
}
}
}
function splitKeywords(keywordString) {
const keywords = keywordString.split(",");
return keywords.map((k) => k.trim());
}
function addCreator(firstName = "", lastName = "", authorId = "") {
const creatorList = document.getElementById("creator-list");
const item = document.createElement("li");
item.setAttribute("class", "list-group-item");
item.innerHTML = `
<div class="form-row">
<div class="col">
<input type="text" class="form-control inputGivenName" placeholder="Vorname" data-i18n-placeholder="LABEL_CREATOR_GIVEN_NAME" value="${firstName}" required>
<div class="valid-feedback"></div>
<div class="invalid-feedback" data-i18n="LABEL_MANDATORY_FIELD">Pflichtfeld</div>
</div>
<div class="col">
<input type="text" class="form-control inputFamilyName" placeholder="Nachname" data-i18n-placeholder="LABEL_CREATOR_LAST_NAME" value="${lastName}" required>
<div class="valid-feedback"></div>
<div class="invalid-feedback" data-i18n="LABEL_MANDATORY_FIELD">Pflichtfeld</div>
</div>
</div>
<div class="form-row">
<div class="col">
<input type="text" class="form-control inputAuthorId" placeholder="Persönliche ID (optional, wie ORCID, GND)" data-i18n-placeholder="LABEL_CREATOR_ID" value="${authorId}">
</div>
</div>
<div class="form-row mt-2">
<div class="col">
<button type="button" onclick="removeCreator(this.parentNode.parentNode.parentNode)" class="btn btn-primary"><i class="fa fa-minus"></i> <span data-i18n="LABEL_CREATOR_REMOVE"> Autor entfernen</span></button>
</div>
</div>
`;
creatorList.insertBefore(item, creatorList.lastElementChild);
updateContent();
}
function removeCreator(creatorListItem) {
creatorListItem.parentNode.removeChild(creatorListItem);
}
function getCreators() {
const creatorsElement = document.getElementById("creator-list").querySelectorAll(".list-group-item");
const creators = [];
for (let i = 0; i < creatorsElement.length - 1; i++) {
const creatorId = creatorsElement[i].getElementsByClassName("inputAuthorId")[0].value;
creators.push({
name: (creatorsElement[i].getElementsByClassName("inputGivenName")[0].value
+ " "
+ creatorsElement[i].getElementsByClassName("inputFamilyName")[0].value).trim(),
id: creatorId ? creatorId : undefined
});
}
return creators;
}
function generate() {
const creators = getCreators()
const inputSourceOrganization = document.getElementById("inputSourceOrganization");
const selectedLanguages = $('#inputLanguage').val();
const selectedSubjects = $('#inputSubjectOf').val();
const selectedResourceTypes = $('#inputResourceType').val();
let meta = {
creativeWorkStatus: document.getElementById("inputStatus").value,
id: document.getElementById("inputUrl").value,
name: document.getElementById("inputTitle").value,
description: document.getElementById("inputDescription").value,
license: {id: document.getElementById("licenseUrl").value}
}
if (creators.length > 0) {
meta.creator = creators
}
if (document.getElementById("inputTags").value) {
meta.keywords = splitKeywords(document.getElementById("inputTags").value)
}
if (selectedLanguages.length > 0) {
meta.inLanguage = selectedLanguages;
}
if (inputSourceOrganization.value) {
meta.sourceOrganization = [
{
name: inputSourceOrganization.options[inputSourceOrganization.selectedIndex].innerHTML,
id: inputSourceOrganization.value,
type: "Organization"
}
]
}
if (selectedSubjects.length > 0) {
meta.about = selectedSubjects.map((s) => ({id: s}))
}
if (document.getElementById("inputImage").value) {
meta.image = document.getElementById("inputImage").value
}
if (selectedResourceTypes.length > 0) {
meta.learningResourceType = selectedResourceTypes.map((t) => ({id: t}))
}
document.getElementById("comment").value = jsyaml.dump(meta);
}
function setCreators(creators) {
const creatorsElement = document.getElementById("creator-list").querySelectorAll(".list-group-item");
for (let i = 0; i < creatorsElement.length - 1; i++) {
removeCreator(creatorsElement[i]);
}
for (let i = 0; i < creators.length; i++) {
const firstName = creators[i].name.split(" ")[0];
const lastName = creators[i].name.substring(creators[i].name.indexOf(" ") + 1);
const authorId = creators[i].id ? creators[i].id : "";
addCreator(firstName, lastName, authorId);
}
}
function importData() {
try {
const data = jsyaml.load(document.getElementById("importData").value);
const sourceOrganizationIds = data.sourceOrganization ? data.sourceOrganization.map((o) => o.id) : [];
const aboutIds = data.about ? data.about.map((o) => o.id) : [];
const learningResourceTypeIds = data.learningResourceType ? data.learningResourceType.map((o) => o.id) : [];
document.getElementById("inputStatus").value = data.creativeWorkStatus ? data.creativeWorkStatus : "Draft";
document.getElementById("inputUrl").value = data.id;
document.getElementById("inputTitle").value = data.name;
setCreators(data.creator ? data.creator : []);
document.getElementById("inputTags").value = data.keywords ? data.keywords.join(", ") : "";
document.getElementById("inputDescription").value = data.description ? data.description : "";
$('#inputLanguage').val(data.inLanguage ? data.inLanguage : []).selectpicker('refresh');
$('#inputSourceOrganization').val(sourceOrganizationIds).selectpicker('refresh');
$('#inputSubjectOf').val(aboutIds).selectpicker('refresh');
setLicense((data.license && data.license.id) ? data.license.id : "")
document.getElementById("inputImage").value = data.image ? data.image : "";
$('#inputResourceType').val(learningResourceTypeIds).selectpicker('refresh');
} catch (e) {
console.warn(e);
alert(i18next.t("LABEL_IMPORT_ERROR_MSG"));
} finally {
$('#importModal').modal('hide')
}
}
function setLicense(license) {
const by = document.getElementById("inputLicenseBY")
const sa = document.getElementById("inputLicenseSA")
const nd = document.getElementById("inputLicenseND")
const nc = document.getElementById("inputLicenseNC")
if (license.startsWith("https://creativecommons.org/publicdomain/zero/")) {
by.checked = true;
sa.checked = true;
nd.checked = true;
nc.checked = true;
} else if (license.startsWith("https://creativecommons.org/licenses/by/")) {
by.checked = false;
sa.checked = true;
nd.checked = true;
nc.checked = true;
} else if (license.startsWith("https://creativecommons.org/licenses/by-sa/")) {
by.checked = false;
sa.checked = false;
nd.checked = true;
nc.checked = true;
} else if (license.startsWith("https://creativecommons.org/licenses/by-nd/")) {
by.checked = false;
sa.checked = true;
nd.checked = false;
nc.checked = true;
} else if (license.startsWith("https://creativecommons.org/licenses/by-nc/")) {
by.checked = false;
sa.checked = true;
nd.checked = true;
nc.checked = false;
} else if (license.startsWith("https://creativecommons.org/licenses/by-nc-sa/")) {
by.checked = false;
sa.checked = false;
nd.checked = true;
nc.checked = false;
} else if (license.startsWith("https://creativecommons.org/licenses/by-nc-nd/")) {
by.checked = false;
sa.checked = true;
nd.checked = false;
nc.checked = false;
} else {
by.checked = false;
sa.checked = false;
nd.checked = false;
nc.checked = false;
}
chooseLicense();
}
async function i18nLoader() {
const langs = ["en", "de"];
const jsons = await Promise.all(
langs.map((l) => fetch("i18n/" + l + ".json").then((r) => r.json()))
);
const hcrt = await Promise.all(
langs.map((l) => fetch("i18n/hcrt-" + l + ".json").then((r) => r.json()))
);
const languageLabels = await Promise.all(
langs.map((l) => fetch("i18n/language-" + l + ".json").then((r) => r.json()))
);
const subjectLabels = await Promise.all(
langs.map((l) => fetch("i18n/subject-" + l + ".json").then((r) => r.json()))
);
const res = langs.reduce((acc, l, idx) => {
acc[l] = {translation: {...jsons[idx], ...hcrt[idx], ...languageLabels[idx], ...subjectLabels[idx]}};
return acc;
}, {});
await i18next.init({
lng: "de",
debug: false,
nsSeparator: "#",
resources: res
});
updateContent();
i18next.on("languageChanged", () => {
updateContent();
});
}
function changeLanguage(languageCode) {
i18next.changeLanguage(languageCode);
document.getElementById("selectedLanguageLabel").textContent = languageCode.toUpperCase();
}
function updateContent() {
let elements = document.querySelectorAll('[data-i18n]');
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const k = element.getAttribute("data-i18n");
element.innerHTML = i18next.t(k);
}
elements = document.querySelectorAll('[data-i18n-placeholder]');
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const k = element.getAttribute("data-i18n-placeholder");
element.setAttribute("placeholder", i18next.t(k));
}
$("[data-i18n-title]").each( function () {
const k = $(this).attr("data-i18n-title")
$(this).selectpicker({title: i18next.t(k)}).selectpicker('render');
})
$('.selectpicker').selectpicker('refresh');
}
</script>
</body>
</html>