Add localization

This commit is contained in:
Julian
2022-02-06 15:30:46 +01:00
parent ce826a833b
commit de5a039995
6 changed files with 272 additions and 41 deletions

View File

@@ -1,3 +1,7 @@
[localization](https://codesandbox.io/s/i18n-example-ipfeu?from-embed=&file=/i18n/de.json:0-652)
Thanks for downloading this theme!
## Other Useful Links

View File

@@ -1135,8 +1135,8 @@ form label {
.plus-button a
{
width: 70px;
height: 70px;
width: 50px;
height: 50px;
background:#F14E95;
display: table;
text-align: center;
@@ -1151,7 +1151,7 @@ form label {
{
display: table-cell;
vertical-align: middle;
height: 60px;
height: 50px;
font-size: 40px;
line-height: 40px;
color: #efefef;

16
i18n/de.json Normal file
View File

@@ -0,0 +1,16 @@
{
"top_left_title": "Hochzeit",
"welcoming_title": "Wir werden am 01.07.2022 heiraten!",
"invitation_text": "Liebe Gäste, zu unserer Hochzeit laden wir euch recht herzlich ein. Bitte gebt uns mit folgendem Formular bis zum 03.03.2022 Bescheid, ob ihr teilnehmt! Über das Plus-Symbol könnt ihr eure Begleitpersonen hinzufügen. Falls ihr nicht teilnehmen könnt, bitte einfach die Seite wieder verlassen. Die Feier wird in 55234 Kettenheim (DE) stattfinden.",
"header_text": "Nimmst du teil?",
"greetings": "Liebe Grüße<br/>Draga & Julian",
"guest_count": "Geschätzte Gäste",
"firstname": "Vorname",
"lastname": "Nachname",
"E-Mail": "E-Mail",
"telephone_number": "Telefonnummer",
"submit": "Absenden",
"already_participating": "Bereits teilgenommen",
"success_title": "Teilgenommen",
"success_text": "Wir freuen uns auf euch!"
}

16
i18n/hr.json Normal file
View File

@@ -0,0 +1,16 @@
{
"top_left_title": "Vjenčanje",
"welcoming_title": "Vjenčajmo se 01.07.2022 !",
"invitation_text": "Dragi gosti, srdačno Vas pozivamo na naše vjenčanje. Molimo vas da nam do 3. ožujka 2022 javite hoćete li sudjelovati putem sljedećeg obrasca! Svoje pratitelje možete dodati putem simbola plus. Ako niste u mogućnosti sudjelovati, jednostavno napustite stranicu. Proslava će se održati u 55234 Kettenheim (Njemačka).",
"header_text": "Hoćete doc?",
"greetings": "Topli pozdravi</br>Draga & Julian",
"guest_count": "broj Gostiju",
"firstname": "Ime",
"lastname": "prezime",
"E-Mail": "E-Mail",
"telephone_number": "broj telefona",
"submit": "podnijeti",
"already_participating": "Već sudjelovali",
"success_title": "Sudjelovali",
"success_text": "Veselimo se vasem sudjelovanju!"
}

View File

@@ -9,7 +9,7 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hochzeit &mdash; 100% Free Fully Responsive HTML5 Template by FREEHTML5.co</title>
<title>Hochzeit</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Free HTML5 Template by FREEHTML5.CO" />
<meta name="keywords" content="free html5, free template, free bootstrap, html5, css3, mobile first, responsive" />
@@ -61,6 +61,9 @@
<!-- Theme style -->
<link rel="stylesheet" href="css/style.css">
<!-- sweetalert2 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.2.0/sweetalert2.min.css">
<!-- Modernizr JS -->
<script src="js/modernizr-2.6.2.min.js"></script>
<!-- FOR IE9 below -->
@@ -78,7 +81,7 @@
<div class="container">
<div class="row">
<div class="col-xs-2">
<div id="fh5co-logo"><a href="index.html">Hochzeit<strong>.</strong></a></div>
<div id="fh5co-logo"><a href="index.html" data-i18n="top_left_title">Hochzeit<strong>.</strong></a></div>
</div>
</div>
@@ -95,7 +98,7 @@
<div class="display-t">
<div class="display-tc animate-box" data-animate-effect="fadeIn">
<h1>Draga &amp; Julian</h1>
<h2>Wir werden am 01.07.2022 heiraten!</h2>
<h2 data-i18n="welcoming_title">Wir werden am 01.07.2022 heiraten!</h2>
<div class="simply-countdown simply-countdown-one"></div>
</div>
</div>
@@ -108,45 +111,52 @@
<div class="container">
<div class="row animate-box">
<div class="col-md-8 col-md-offset-2 text-center fh5co-heading">
<h2>Nimmst du teil?</h2>
<p>Liebe Gäste, zu unserer Hochzeit laden wir euch recht herzlich ein. Bitte gebt uns mit
<h2 data-i18n="header_text">Nimmst du teil?</h2>
<p data-i18n="invitation_text">Liebe Gäste, zu unserer Hochzeit laden wir euch recht herzlich ein. Bitte gebt uns mit
folgendem Formular bis zum 03.03.2022 Bescheid, ob ihr teilnehmt! Über das Plus-Symbol könnt
ihr eure Begleitpersonen hinzufügen.
Falls ihr nicht teilnehmen könnt, bitte einfach die Seite wieder verlassen. Die Feier wird
in 55234 Kettenheim (DE)
stattfinden.
</p>
<p>
Liebe Grüße</br>
<p data-i18n="greetings">
Liebe Grüße<br/>
Draga & Julian
</p>
</div>
</div>
<div class="row animate-box">
<div class="row animate-box" id="attentant-container">
<div class="col-md-10">
<form id="js-attentants" class="form-inline">
<div>
<div class="col-md-4 col-sm-4">
<div class="col-md-3 col-sm-3">
<div class="form-group">
<label for="firstname" class="sr-only">Vorname</label>
<input type="firstname" class="form-control" id="firstname"
<input type="firstname" class="form-control" id="firstname" data-i18n="firstname" data-i18n-attr="placeholder"
placeholder="Vorname">
</div>
</div>
<div class="col-md-4 col-sm-4">
<div class="col-md-3 col-sm-3">
<div class="form-group">
<label for="lastname" class="sr-only">Nachname</label>
<input type="lastname" class="form-control" id="lastname"
<input type="lastname" class="form-control" id="lastname" data-i18n="lastname" data-i18n-attr="placeholder"
placeholder="Nachname">
</div>
</div>
<div class="col-md-4 col-sm-4">
<div class="col-md-3 col-sm-3">
<div class="form-group">
<label for="tel" class="sr-only">Telefonnummer</label>
<input type="telephon" class="form-control" id="tel"
<input type="telephon" class="form-control" id="tel" data-i18n="telephone_number" data-i18n-attr="placeholder"
placeholder="Telefonnummer">
</div>
</div>
<div class="col-md-3 col-sm-3">
<div class="form-group">
<label for="email" class="sr-only">E-Mail Addresse</label>
<input type="email" class="form-control" id="email" data-i18n="E-Mail" data-i18n-attr="placeholder"
placeholder="E-Mail">
</div>
</div>
</div>
</form>
</div>
@@ -159,7 +169,7 @@
</div>
<div class="row animate-box">
<div class="col-md-4 col-md-offset-4 text-center fh5co-heading">
<button type="submit" id="js-submitbtn" class="btn btn-default btn-block">Absenden</button>
<button type="submit" id="js-submitbtn" data-i18n="submit" class="btn btn-default btn-block">Absenden</button>
</div>
</div>
<div class="row animate-box" style="margin-top: 50px;">
@@ -170,7 +180,7 @@
</span>
<span class="counter js-counter" data-from="0" data-to="500" data-speed="5000"
data-refresh-interval="50">1</span>
<span class="counter-label">Geschätzte Gäste</span>
<span class="counter-label" data-i18n="guest_count">Geschätzte Gäste</span>
</div>
</div>
</div>
@@ -182,7 +192,6 @@
<div class="gototop js-top">
<a href="#" class="js-gotop"><i class="icon-arrow-up"></i></a>
</div>
<!-- jQuery -->
<script src="js/jquery.min.js"></script>
<!-- jQuery Easing -->
@@ -200,7 +209,8 @@
<!-- Magnific Popup -->
<script src="js/jquery.magnific-popup.min.js"></script>
<script src="js/magnific-popup-options.js"></script>
<!-- Sweetalert2 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.2.0/sweetalert2.min.js"></script>
<!-- // <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/0.0.1/prism.min.js"></script> -->
<script src="js/simplyCountdown.js"></script>
<!-- Main -->
@@ -212,17 +222,17 @@
// default example
simplyCountdown('.simply-countdown-one', {
year: d.getFullYear(),
month: d.getMonth() + 1,
month: d.getMonth(),
day: d.getDate()
});
//jQuery example
$('#simply-countdown-losange').simplyCountdown({
year: d.getFullYear(),
month: d.getMonth() + 1,
day: d.getDate(),
enableUtc: false
});
// $('#simply-countdown-losange').simplyCountdown({
// year: d.getFullYear(),
// month: d.getMonth() + 1,
// day: d.getDate(),
// enableUtc: false
// });
</script>
</body>

View File

@@ -182,8 +182,8 @@
};
var addField = function() {
$('.js-addField').on('click', function(event){
var addField = async function() {
$('.js-addField').on('click', async function(event){
event.preventDefault();
@@ -219,7 +219,8 @@
inputElement.setAttribute("type","firstname");
inputElement.classList.add('form-control');
inputElement.setAttribute("id","firstname");
inputElement.setAttribute("placeholder","Vorname");
let firstname_placeholder = await translator.getTranslationByKey(document.documentElement.lang,"firstname");
inputElement.setAttribute("placeholder", firstname_placeholder);
formGroupDiv.appendChild(inputElement);
outerDiv.appendChild(firstNameDiv);
@@ -244,13 +245,14 @@
firstNameInputElement.setAttribute("type","lastname");
firstNameInputElement.classList.add('form-control');
firstNameInputElement.setAttribute("id","lastname");
firstNameInputElement.setAttribute("placeholder","Nachname");
let lastname_placeholder = await translator.getTranslationByKey(document.documentElement.lang,"lastname");
firstNameInputElement.setAttribute("placeholder", lastname_placeholder);
lastnameFormGroupDiv.appendChild(firstNameInputElement);
outerDiv.appendChild(lastNameDiv);
container.appendChild(outerDiv);
return false;
});
}
@@ -304,12 +306,7 @@
}());
//var form = document.getElementById("js-submitbtn");
document.getElementById("js-submitbtn").addEventListener("click", function () {
document.getElementById("js-submitbtn").addEventListener("click", async function () {
//form.submit();
//console.log("Hello world!");
@@ -319,8 +316,196 @@ document.getElementById("js-submitbtn").addEventListener("click", function () {
console.log("Vorname:" + inputs[0].value);
console.log("Nachname:" + inputs[1].value);
console.log("Telefon:" + inputs[2].value);
for (let i = 3; i < inputs.length; i+=2) {
console.log("E-Mail:" + inputs[3].value);
for (let i = 4; i < inputs.length; i+=2) {
console.log("Mitbringsel:" + inputs[i].value, inputs[i+1].value);
}
});
//Swal.fire("Our First Alert", "With some body text and success icon!", "success");
document.getElementById("attentant-container").remove();
document.getElementById("js-submitbtn").disabled = 'true';
document.getElementById("js-submitbtn").textContent = await translator.getTranslationByKey(document.documentElement.lang,"already_participating");
let title = 'Teilgenommen';
let text = "Wir freuen uns auf euch!";
title = await translator.getTranslationByKey(document.documentElement.lang,"success_title");
text = await translator.getTranslationByKey(document.documentElement.lang,"success_text");
console.log(document.documentElement.lang);
swal({
title: title,
text: text,
type: 'success',
showConfirmButton: false,
timer: 2000
}).then(function () {
// swal( 'Ready?!', 'Your form is going to be submitted.' 'success');
//document.querySelector('#myfrm').submit(); // manully submit
}).catch(function(timeout) { });
//TODO: Refresh attentats count
});
class Translator {
constructor(options = {}) {
this._options = Object.assign({}, this.defaultConfig, options);
this._elements = document.querySelectorAll("[data-i18n]");
this._cache = new Map();
if (this._options.detectLanguage) {
this._options.defaultLanguage = this._detectLanguage();
}
if (
this._options.defaultLanguage &&
typeof this._options.defaultLanguage == "string"
) {
this._getResource(this._options.defaultLanguage);
}
}
_detectLanguage() {
var stored = localStorage.getItem("language");
if (this._options.persist && stored) {
return stored;
}
var lang = navigator.languages
? navigator.languages[0]
: navigator.language;
return lang.substr(0, 2);
}
_fetch(path) {
return fetch(path)
.then(response => response.json())
.catch(() => {
console.error(
`Could not load ${path}. Please make sure that the file exists.`
);
});
}
async _getResource(lang) {
if (this._cache.has(lang)) {
return JSON.parse(this._cache.get(lang));
}
var translation = await this._fetch(
`${this._options.filesLocation}/${lang}.json`
);
if (!this._cache.has(lang)) {
this._cache.set(lang, JSON.stringify(translation));
}
return translation;
}
async load(lang) {
if (!this._options.languages.includes(lang)) {
return;
}
this._translate(await this._getResource(lang));
document.documentElement.lang = lang;
if (this._options.persist) {
localStorage.setItem("language", lang);
}
}
async getTranslationByKey(lang, key) {
if (!key) throw new Error("Expected a key to translate, got nothing.");
if (typeof key != "string")
throw new Error(
`Expected a string for the key parameter, got ${typeof key} instead.`
);
var translation = await this._getResource(lang);
return this._getValueFromJSON(key, translation, true);
}
_getValueFromJSON(key, json, fallback) {
var text = key.split(".").reduce((obj, i) => obj[i], json);
if (!text && this._options.defaultLanguage && fallback) {
let fallbackTranslation = JSON.parse(
this._cache.get(this._options.defaultLanguage)
);
text = this._getValueFromJSON(key, fallbackTranslation, false);
} else if (!text) {
text = key;
console.warn(`Could not find text for attribute "${key}".`);
}
return text;
}
_translate(translation) {
var zip = (keys, values) => keys.map((key, i) => [key, values[i]]);
var nullSafeSplit = (str, separator) => (str ? str.split(separator) : null);
var replace = element => {
var keys = nullSafeSplit(element.getAttribute("data-i18n"), " ") || [];
var properties = nullSafeSplit(
element.getAttribute("data-i18n-attr"),
" "
) || ["innerHTML"];
if (keys.length > 0 && keys.length !== properties.length) {
console.error(
"data-i18n and data-i18n-attr must contain the same number of items"
);
} else {
var pairs = zip(keys, properties);
pairs.forEach(pair => {
const [key, property] = pair;
var text = this._getValueFromJSON(key, translation, true);
if (text) {
element[property] = text;
element.setAttribute(property, text);
} else {
console.error(`Could not find text for attribute "${key}".`);
}
});
}
};
this._elements.forEach(replace);
}
get defaultConfig() {
return {
persist: false,
languages: ["de"],
defaultLanguage: "",
detectLanguage: true,
filesLocation: "/i18n"
};
}
}
var translator = new Translator({
persist: false,
languages: ["hr", "de"],
defaultLanguage: "hr",
detectLanguage: true,
filesLocation: "/i18n"
});
translator.load("hr");