feat: update locale to be more smart
This commit is contained in:
parent
4dd1cf209b
commit
ff01197ee6
5 changed files with 98 additions and 30 deletions
30
README.md
30
README.md
|
@ -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"` |
|
||||
| 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"` |
|
|
@ -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];
|
||||
})
|
||||
})
|
||||
})
|
||||
})()
|
22
test.html
22
test.html
|
@ -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>
|
||||
|
|
27
test.json
27
test.json
|
@ -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
3
x0.js
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue