minor: rework intl with mutationobserver + admin search fields

This commit is contained in:
Jean-Baptiste Pasquier 2021-01-26 17:48:05 +01:00
parent eb31b5b9d9
commit 7c0f237bd0
8 changed files with 89 additions and 50 deletions

View File

@ -68,7 +68,7 @@
"create": {
"backlink": "Back",
"title": " Create a circle",
"labelStatus": "Statut du circle",
"labelStatus": "Circle status",
"labelName": "Circle name *",
"labelSubtitle": "Circle headline *",
"labelDescription": "Circle description",
@ -100,7 +100,8 @@
"tableHeader2": "Admins",
"tableHeader3": "Join",
"buttonQuit": "Leave",
"buttonJoin": "Join"
"buttonJoin": "Join",
"searchBy": "Find a circle by name"
},
"left": {
"paragraphQuit": "You left this circle.",
@ -126,7 +127,8 @@
"noPermission": "Member, no permission",
"subTitle": "Communities",
"tableHeader1": "Name",
"tableHeader2": "Action"
"tableHeader2": "Action",
"searchBy": "Find a community by name"
},
"project": {
"menuRight": {
@ -142,7 +144,6 @@
"labelDescription": "Poject description",
"descriptionHelp": "You can use markdown",
"labelCustomer": "Customer name*",
"labelDescription": "Description",
"labelCaptain": "Project captain*",
"buttonSubmit": "Save"
},
@ -175,7 +176,8 @@
"tableHeader3": "Captains",
"tableHeader4": "Join",
"buttonQuit": "Leave",
"buttonJoin":"Join"
"buttonJoin":"Join",
"searchBy": "Find a project by name"
},
"left": {
"paragraphQuit": "You left this project.",

View File

@ -100,7 +100,8 @@
"tableHeader2": "Administradorxs",
"tableHeader3": "Unirse",
"buttonQuit": "Salir",
"buttonJoin": "Unirse"
"buttonJoin": "Unirse",
"searchBy": "Busca un círculo por nombre "
},
"left": {
"paragraphQuit": "Dejaste este círculo.",
@ -126,7 +127,8 @@
"noPermission": "Miembrx sin permiso",
"subTitle": "Comunidades",
"tableHeader1": "Nombre",
"tableHeader2": "Acción"
"tableHeader2": "Acción",
"searchBy": "Encuentra una comunidad por nombre "
},
"project": {
"menuRight": {
@ -142,7 +144,6 @@
"labelDescription": "Descripción del proyecto",
"descriptionHelp": "Puedes usar markdown",
"labelCustomer": "Nombre del/la clientx *",
"labelDescription": "Description",
"labelCaptain": "Líder del proyecto *",
"buttonSubmit": "Guardar"
},
@ -175,7 +176,8 @@
"tableHeader3": "Líderes",
"tableHeader4": "Unirse",
"buttonQuit": "Salir",
"buttonJoin": "Unirse"
"buttonJoin": "Unirse",
"searchBy": "Buscar un proyecto por nombre "
},
"left": {
"paragraphQuit": "Dejaste este proyecto.",

View File

@ -101,7 +101,8 @@
"tableHeader2": "Administrateurs",
"tableHeader3": "Rejoindre",
"buttonQuit": "Quitter",
"buttonJoin": "Rejoindre"
"buttonJoin": "Rejoindre",
"searchBy": "Rechercher un cercle par nom"
},
"left": {
"paragraphQuit": "Tu as quitté ce cercle.",
@ -127,7 +128,8 @@
"noPermission": "Membre, aucune permission",
"subTitle": "Communautés",
"tableHeader1": "Nom",
"tableHeader2": "Action"
"tableHeader2": "Action",
"searchBy": "Rechercher une communauté par nom"
},
"project": {
"menuRight": {
@ -143,7 +145,6 @@
"labelDescription": "Description du projet",
"descriptionHelp": "Vous pouvez utiliser Markdown",
"labelCustomer": "Nom du client*",
"labelDescription": "Description",
"labelCaptain": "Capitaine du projet*",
"buttonSubmit": "Enregistrer"
},
@ -176,7 +177,8 @@
"tableHeader3": "Capitaines",
"tableHeader4": "Rejoindre",
"buttonQuit": "Quitter",
"buttonJoin":"Rejoindre"
"buttonJoin":"Rejoindre",
"searchBy": "Rechercher un projet par nom"
},
"left": {
"paragraphQuit": "Tu as quitté ce projet.",

View File

@ -39,12 +39,18 @@ class JsI18n {
if (attr == "html") {
this.translateNodeContent(node, k);
} else {
if(node.tagName == "SOLID-DELETE") {
if (node.tagName == "SOLID-DELETE") {
let button = node.querySelector('button');
if(button != null) {
if (button != null) {
this.translateNodeContent(button, k);
}
}
if (attr.startsWith('label-')) {
let label = node.querySelector('[name="'+attr.replace("label-", "")+'"] > label');
if(label != null) {
this.translateNodeContent(label, k);
}
}
this.translateNodeContent(node.attributes[attr], k);
}
}
@ -60,12 +66,15 @@ class JsI18n {
if (node != null && translation != undefined) {
if (node.nodeType == 1) { //Element
try {
node.innerHTML = translation;
if(node.innerHTML != translation)
node.innerHTML = translation;
} catch (e) {
node.text = translation;
if(node.text != translation)
node.text = translation;
}
} else if (node.nodeType == 2) { //Attribute
node.value = translation;
if(node.value != translation)
node.value = translation;
}
}
}
@ -120,12 +129,12 @@ class JsI18n {
}
});
} else {
if (locale != "fr") {
console.warn(`Locale not found: ${locale}, fallback to french`);
this.setLocale("fr");
} else {
console.error("Language not found");
}
if (locale != "fr") {
console.warn(`Locale not found: ${locale}, fallback to french`);
this.setLocale("fr");
} else {
console.error("Language not found");
}
}
});
this.locale = locale;
@ -146,7 +155,7 @@ class JsI18n {
var translations = this.locales[this.locale];
if (translations != undefined) {
let translation = key.toString().split('.').reduce((o, i) => (o ? o[i] : undefined), translations);
if(typeof translation == "string") {
if (typeof translation == "string") {
return translation;
} else {
return translations[key.toString()];
@ -178,25 +187,17 @@ document.addEventListener("DOMContentLoaded", () => {
// Detect the lang & initialize, based on the browser or "language" item from localstorage
jsI18n.detectLanguage();
/*
recursivePopulate(DOMElement)
Will listen for the populate event of any sib element
Process the changed node every time it populate
Recursively add a populate listener for children elements
*/
function recursivePopulate(element) {
Array.from(element.querySelectorAll('*')).forEach((e) => {
if(e.content && e.content instanceof DocumentFragment) {
recursivePopulate(e.content);
} else if(e instanceof HTMLElement) {
e.addEventListener("populate", (el) => {
recursivePopulate(el.target);
jsI18n.processNode(el.target);
});
(new MutationObserver((mutations) => {
mutations.forEach(mutation => {
if(mutation.target.attributes["data-trans"] != null) {
// Render the target of the mutation instantly
jsI18n.processNode(mutation.target);
// Then wait one arbitrary second to re-render the whole document in case a widget re-rendered
setTimeout(() => jsI18n.processNode(document.querySelector('body')), 1000);
}
});
}
// Process every children from document
recursivePopulate(document);
}).observe(document.body, {
subtree: true,
childList: true
}));
});

View File

@ -83,6 +83,15 @@ div.segment.full.padding-large.sm-padding-xsmall.sm-padding-top-normal.whitespac
widget-name='admin-circle-link'
)
solid-form-search.form(
id="admin-circle-filter"
fields='name'
label-name=''
data-trans='label-name=circle.list.searchBy'
widget-name='solid-form-label-text'
class-name="segment margin-bottom-medium half sm-full padding-right-small sm-padding-none text-small text-semibold text-uppercase text-color-heading"
)
.segment.table-wrapper
.table
@ -122,9 +131,10 @@ div.segment.full.padding-large.sm-padding-xsmall.sm-padding-top-normal.whitespac
solid-display(
class='table-body'
filtered-by="admin-circle-filter"
bind-user
nested-field='circles'
fields='cell1(circle.name, counter, circle.subtitle), cell2(circle.owner), cell3(leaveButton)'
fields='cell1(name(circle.name), counter, circle.subtitle), cell2(circle.owner), cell3(leaveButton)'
loader-id='loader-admin-circles'
class-cell1='segment table-cell third whitespace-normal'
@ -154,7 +164,7 @@ div.segment.full.padding-large.sm-padding-xsmall.sm-padding-top-normal.whitespac
value-user.username='hubl-workaround-493'
widget-user.username='solid-form-hidden'
submit-button='Join'
submit-button=''
data-trans='submit-button=circle.list.buttonJoin'
)
hubl-reactivity(data-src=`${endpoints.get.circles}` target-src='${value}')
@ -165,6 +175,7 @@ div.segment.full.padding-large.sm-padding-xsmall.sm-padding-top-normal.whitespac
solid-display(
class='table-body'
filtered-by="admin-circle-filter"
data-src=`${endpoints.circles || endpoints.get.circles}joinable/`
fields='cell1(name, counter, subtitle), cell2(owner), cell3(members)'

View File

@ -29,6 +29,15 @@ div.segment.full.padding-large.sm-padding-xsmall.sm-padding-top-medium.whitespac
)
span.icon.icon-people.icon-xsmall.margin-right-xxsmall
solid-form-search.form(
id="admin-community-filter"
fields='cell1'
label-cell1=''
data-trans='label-cell1=communities.searchBy'
widget-cell1='solid-form-label-text'
class-cell1="segment margin-bottom-medium half sm-full padding-right-small sm-padding-none text-small text-semibold text-uppercase text-color-heading"
)
.segment.table-wrapper
.table
div.table-header.bg-color-third.text-color-heading
@ -37,6 +46,7 @@ div.segment.full.padding-large.sm-padding-xsmall.sm-padding-top-medium.whitespac
solid-display(
class='table-body'
filtered-by='admin-community-filter'
bind-user
nested-field='communities'
fields='cell1(community.name, counter), cell2(community)'

View File

@ -58,6 +58,15 @@ div.segment.full.padding-large.sm-padding-xsmall.sm-padding-top-medium.whitespac
widget-name='admin-project-link'
)
solid-form-search.form(
id="admin-project-filter"
fields='cell1'
label-cell1=''
data-trans='label-cell1=project.list.searchBy'
widget-cell1='solid-form-label-text'
class-cell1="segment margin-bottom-medium half sm-full padding-right-small sm-padding-none text-small text-semibold text-uppercase text-color-heading"
)
.segment.table-wrapper
.table
@ -132,6 +141,7 @@ div.segment.full.padding-large.sm-padding-xsmall.sm-padding-top-medium.whitespac
solid-display(
class='table-body'
filtered-by="admin-project-filter"
bind-user
nested-field="projects"
@ -180,6 +190,7 @@ div.segment.full.padding-large.sm-padding-xsmall.sm-padding-top-medium.whitespac
solid-display(
class='table-body'
filtered-by="admin-project-filter"
data-src=`${endpoints.projects || endpoints.get.projects}joinable/`
fields='cell1(customer.name, counter, name), cell2(members), cell3(captain), cell4(joinButton)'

View File

@ -20,14 +20,14 @@ div.segment.full.padding-large.sm-padding-xsmall.sm-padding-top-medium.whitespac
solid-widget(name='hubl-username-field')
template
label(data-trans='user.create.labelUsername')
input(type="text" title='' pattern="[a-zA-Z0-9]+" label="" data-trans='title=user.create.labelUsernameTitle;label=user.create.labelUsername' name="username" required value="\${value}" data-holder)
label ${label}
input(type="text" title='' pattern="[a-zA-Z0-9]+" label="${label}" data-trans='title=user.create.labelUsernameTitle' name="username" required value="\${value}" data-holder)
solid-widget(name='hubl-email-field')
template
div.segment.margin-bottom-medium.half.sm-full.padding-left-small.sm-padding-none.text-small.text-semibold.text-uppercase.text-color-heading
label(data-trans='user.create.labelEmail')
input(type="email" label='' data-trans='label=user.create.labelEmail' name="email" required value="\${value}" data-holder)
label ${label}
input(type="email" label='${label}' name="email" required value="\${value}" data-holder)
div.segment.margin-bottom-medium
div.segment