feat: update locale to be more smart

This commit is contained in:
Strix 2023-12-24 20:40:28 +01:00
parent 4dd1cf209b
commit ff01197ee6
No known key found for this signature in database
GPG key ID: 5F35B3B8537287A7
5 changed files with 98 additions and 30 deletions

View file

@ -10,21 +10,27 @@ It has some attributes that simplify stuff with js.
### Top level attributes
These attributes only work on, and modify the root element (query selector: `html`).
These attributes only work on the html tag.
| attrib | description | default |
| ---------------- | ------------------------------- | --------------- |
| `x0-mods` | what modules to include | nothing |
| `x0-module-root` | where to fetch the modules from | `./x0/modules/` |
| `x0-init` | init x0? | `true` |
| attrib | description | default | module |
| -------------------- | ----------------------------------------------------- | --------------- | ------ |
| `x0-mods` | what modules to include | nothing | x0 |
| `x0-module-root` | where to fetch the modules from | `./x0/modules/` | x0 |
| `x0-init` | init x0? | `true` | x0 |
| `x0-locale-file` | which locale file to use | nothing | locale |
| `x0-locale-watch` | add an onchange listener to update locales | | locale |
| `x0-locale-no-cache` | do **not** use cached locales | | locale |
| `x0-locale-default` | default locale | `en` | locale |
| `x0-locale-prefer` | set a preferred locale; ignore users lang if possible | | locale |
### Element Attributes
Attributes you can use
| module | attrib | description | example |
| --------- | ---------------- | ----------------------------------------------------------- | ------------------------- |
| --------- | ---------------- | ----------------------------------------------------------- | ------------------------------ |
| http | `x-get` | set the element's contents to the result of the get request | `x-get="./content"` |
| http | `x-get-interval` | use with `x-get` to poll the endpoint (millis) | `x-get-interval=1000` |
| http,copy | `x-inner-html` | instead of using innerHTML use innerText | `x-inner-html` |
| copy | `x-copy-query` | copy contents of element matching query selector | `x-copy-query="#content"` |
| locale | `x-locale-key` | fetch locale key and put it in innerHTML | `x-locale-key="main.greeting"` |

View file

@ -1,10 +1,22 @@
// [x-locale-key="<key>"]
// html[x1-locale-file] -
// html[x1-locale-watch] - watch document for changes and update
// html[x0-locale-file="<url>"] - which file to use for locale
// html[x0-locale-no-cache] - do not cache locale
// html[x0-locale-watch] - watch document for changes and update
// html[x0-locale-default="en"] - default "en"
// html[x0-locale-prefer="en"] - prefer locale "en"
(async () => {
if (!document.querySelector("html").hasAttribute("x1-locale-file")) return;
if (!document.querySelector("html").hasAttribute("x0-locale-file")) return;
const getLocale = async (url) => {
let locale = (document.querySelector("html").hasAttribute("x0-locale-no-cache") ? undefined : localStorage.getItem(url)) ?? (await (await fetch(url)).text());
if (!document.querySelector("html").hasAttribute("x0-locale-no-cache"))
fetch(url).then(r => r.text().then(t => localStorage.setItem(url, t)));
localStorage.setItem(url, locale);
return JSON.parse(locale);
};
let backupElements = window.x0?.registerStorage("locale") ?? {};
let locale = (await (await fetch(document.querySelector("html").getAttribute("x1-locale-file"))).json()) ?? {};
let locale = await getLocale(document.querySelector("html").getAttribute("x0-locale-file")) ?? {};
const getValueFromPath = (obj, path) => path.split(".").reduce((obj, key) => obj && obj[key], obj);
@ -13,8 +25,23 @@
.forEach(e => {
let uuid = (Math.random() + new Date().getTime()).toString(36);
e.setAttribute("x1-locale-uuid", uuid);
backupElements[uuid] = e.outerHTML;
e.innerHTML = getValueFromPath(locale, e.getAttribute("x-locale-key"));
backupElements[uuid] = e.innerHTML;
let v = getValueFromPath(locale, e.getAttribute("x-locale-key"));
if (typeof v === 'object') {
[
document.querySelector("html").getAttribute("x0-locale-prefer"),
new URLSearchParams(window.location.search).get("locale"),
navigator.userLanguage || navigator.language || navigator.browserLanguage,
...navigator.languages,
document.querySelector("html").getAttribute("x0-locale-default") ?? "en"
]
.filter(l => l)
.map(l => l.toLowerCase())
.forEach(l => v = v[l] ?? v)
if (typeof v === 'object')
v = '%%definition not found%%'
}
e.innerHTML = v;
})
}
@ -26,9 +53,14 @@
window.x0?.registerModuleUpdateHook("locale", updateLocale);
window.x0?.registerModuleRemoveHook("locale", (s) => {
console.log(s);
Object.keys(s)
.forEach(uuid => {
document.querySelector(`[x1-locale-uuid="${uuid}"]`).outerHTML = s[uuid];
let el = document.querySelector(`[x1-locale-uuid="${uuid}"]`);
requestAnimationFrame(() => {
el.removeAttribute("x1-locale-uuid");
el.innerHTML = s[uuid];
})
})
})
})()

View file

@ -1,22 +1,32 @@
<html
x0-mods="locale,copy,http"
x0-module-root="./modules/"
x0-init="false"
x1-locale-file="./test.json"
x1-locale-watch
x0-locale-file="./test.json"
x0-locale-watch
>
<body>
<button onclick="window.x0.update()">Update x0</button>
<button onclick="window.location.reload()">Reload page</button>
<button onclick="window.location.reload()" x-locale-key="debug-tools.reload">Reload page</button>
<input type="text" onfocus="this.value = document.querySelector('html').getAttribute('x0-mods')" onchange="document.querySelector('html').setAttribute('x0-mods', this.value); document.querySelector('#status').innerHTML='updated x0-mods'; window.x0.update(); setInterval(() => document.querySelector('#status').innerHTML = '', 500)">
<span id="status"></span>
<h1 x-locale-key="main.greeting"></h1>
<h1 x-locale-key="main.greeting">main.greeting</h1>
<div>
<h2 x-locale-key="copy-section.header"></h2>
<div id="ex">
<span x-locale-key="copy-section.content-span"></span>
<span x-locale-key="copy-section.content-span">origin</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
<span x-locale-key="copy-section.content-span">duplicate</span>
</div>
<div x-copy-query="#ex"></div>
</div>

View file

@ -1,12 +1,31 @@
{
"debug-tools": {
"update": "Update x0",
"reload": {
"nl": "Herlaad Pagina",
"en": "Reload Page"
}
},
"main": {
"greeting": "Welcome to the test page!"
"greeting": {
"nl": "Welkom op de test pagina!",
"en": "Welcome on the test page!"
}
},
"copy-section": {
"header": "Copy",
"content-span": "Original Content"
"header": {
"nl": "Kopiëer functie",
"en": "Copy function"
},
"content-span": {
"en": "Original Content",
"nl": "Originele Content"
}
},
"http-section": {
"header": "http"
"header": {
"nl": "HTTP Functie",
"en": "HTTP function"
}
}
}

3
x0.js
View file

@ -77,7 +77,8 @@ class x0 {
/** registerStorage
* Register a storage.
* This can only happen once per module.
* This storage's lifetime is one page load.
* This can only happen once per module per page load.
*/
registerStorage(module) {
if (this.#moduleStorage[module]) return null;