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
20
README.md
20
README.md
|
@ -10,21 +10,27 @@ It has some attributes that simplify stuff with js.
|
||||||
|
|
||||||
### Top level attributes
|
### 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 |
|
| attrib | description | default | module |
|
||||||
| ---------------- | ------------------------------- | --------------- |
|
| -------------------- | ----------------------------------------------------- | --------------- | ------ |
|
||||||
| `x0-mods` | what modules to include | nothing |
|
| `x0-mods` | what modules to include | nothing | x0 |
|
||||||
| `x0-module-root` | where to fetch the modules from | `./x0/modules/` |
|
| `x0-module-root` | where to fetch the modules from | `./x0/modules/` | x0 |
|
||||||
| `x0-init` | init x0? | `true` |
|
| `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
|
### Element Attributes
|
||||||
|
|
||||||
Attributes you can use
|
Attributes you can use
|
||||||
|
|
||||||
| module | attrib | description | example |
|
| 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` | 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 | `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` |
|
| 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"` |
|
| 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>"]
|
// [x-locale-key="<key>"]
|
||||||
// html[x1-locale-file] -
|
// html[x0-locale-file="<url>"] - which file to use for locale
|
||||||
// html[x1-locale-watch] - watch document for changes and update
|
// 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 () => {
|
(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 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);
|
const getValueFromPath = (obj, path) => path.split(".").reduce((obj, key) => obj && obj[key], obj);
|
||||||
|
|
||||||
|
@ -13,8 +25,23 @@
|
||||||
.forEach(e => {
|
.forEach(e => {
|
||||||
let uuid = (Math.random() + new Date().getTime()).toString(36);
|
let uuid = (Math.random() + new Date().getTime()).toString(36);
|
||||||
e.setAttribute("x1-locale-uuid", uuid);
|
e.setAttribute("x1-locale-uuid", uuid);
|
||||||
backupElements[uuid] = e.outerHTML;
|
backupElements[uuid] = e.innerHTML;
|
||||||
e.innerHTML = getValueFromPath(locale, e.getAttribute("x-locale-key"));
|
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?.registerModuleUpdateHook("locale", updateLocale);
|
||||||
|
|
||||||
window.x0?.registerModuleRemoveHook("locale", (s) => {
|
window.x0?.registerModuleRemoveHook("locale", (s) => {
|
||||||
|
console.log(s);
|
||||||
Object.keys(s)
|
Object.keys(s)
|
||||||
.forEach(uuid => {
|
.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
|
<html
|
||||||
x0-mods="locale,copy,http"
|
x0-mods="locale,copy,http"
|
||||||
x0-module-root="./modules/"
|
x0-module-root="./modules/"
|
||||||
x0-init="false"
|
x0-locale-file="./test.json"
|
||||||
x1-locale-file="./test.json"
|
x0-locale-watch
|
||||||
x1-locale-watch
|
|
||||||
>
|
>
|
||||||
<body>
|
<body>
|
||||||
<button onclick="window.x0.update()">Update x0</button>
|
<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)">
|
<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>
|
<span id="status"></span>
|
||||||
|
|
||||||
<h1 x-locale-key="main.greeting"></h1>
|
<h1 x-locale-key="main.greeting">main.greeting</h1>
|
||||||
<div>
|
<div>
|
||||||
<h2 x-locale-key="copy-section.header"></h2>
|
<h2 x-locale-key="copy-section.header"></h2>
|
||||||
|
|
||||||
<div id="ex">
|
<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>
|
||||||
<div x-copy-query="#ex"></div>
|
<div x-copy-query="#ex"></div>
|
||||||
</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": {
|
"main": {
|
||||||
"greeting": "Welcome to the test page!"
|
"greeting": {
|
||||||
|
"nl": "Welkom op de test pagina!",
|
||||||
|
"en": "Welcome on the test page!"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"copy-section": {
|
"copy-section": {
|
||||||
"header": "Copy",
|
"header": {
|
||||||
"content-span": "Original Content"
|
"nl": "Kopiëer functie",
|
||||||
|
"en": "Copy function"
|
||||||
|
},
|
||||||
|
"content-span": {
|
||||||
|
"en": "Original Content",
|
||||||
|
"nl": "Originele Content"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"http-section": {
|
"http-section": {
|
||||||
"header": "http"
|
"header": {
|
||||||
|
"nl": "HTTP Functie",
|
||||||
|
"en": "HTTP function"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
3
x0.js
3
x0.js
|
@ -77,7 +77,8 @@ class x0 {
|
||||||
|
|
||||||
/** registerStorage
|
/** registerStorage
|
||||||
* Register a storage.
|
* 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) {
|
registerStorage(module) {
|
||||||
if (this.#moduleStorage[module]) return null;
|
if (this.#moduleStorage[module]) return null;
|
||||||
|
|
Loading…
Reference in a new issue