translation pipeline: working.
This commit is contained in:
parent
3025b6d50a
commit
2ecb2ab1fd
129
css/style.css
129
css/style.css
|
|
@ -1,5 +1,134 @@
|
||||||
|
:root {
|
||||||
|
/* size variables */
|
||||||
|
/* more pronounced, perfect fifth on narrow screens */
|
||||||
|
/* @link https://utopia.fyi/type/calculator?c=360,16,1.5,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
|
||||||
|
|
||||||
|
--step--2: clamp(0.4444rem, 0.299rem + 0.6465vw, 0.8rem);
|
||||||
|
--step--1: clamp(0.6667rem, 0.5303rem + 0.6061vw, 1rem);
|
||||||
|
--step-0: clamp(1rem, 0.8977rem + 0.4545vw, 1.25rem);
|
||||||
|
--step-1: clamp(1.5rem, 1.4744rem + 0.1136vw, 1.5625rem);
|
||||||
|
--step-2: clamp(1.9531rem, 2.3714rem + -0.5398vw, 2.25rem);
|
||||||
|
--step-3: clamp(2.4414rem, 3.7569rem + -1.6974vw, 3.375rem);
|
||||||
|
--step-4: clamp(3.0518rem, 5.8851rem + -3.6559vw, 5.0625rem);
|
||||||
|
--step-5: clamp(3.8147rem, 9.1397rem + -6.871vw, 7.5938rem);
|
||||||
|
|
||||||
|
/* @link https://utopia.fyi/space/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
|
||||||
|
|
||||||
|
--space-3xs: clamp(0.3125rem, 0.3125rem + 0vw, 0.3125rem);
|
||||||
|
--space-2xs: clamp(0.5625rem, 0.5369rem + 0.1136vw, 0.625rem);
|
||||||
|
--space-xs: clamp(0.875rem, 0.8494rem + 0.1136vw, 0.9375rem);
|
||||||
|
--space-s: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem);
|
||||||
|
--space-m: clamp(1.6875rem, 1.6108rem + 0.3409vw, 1.875rem);
|
||||||
|
--space-l: clamp(2.25rem, 2.1477rem + 0.4545vw, 2.5rem);
|
||||||
|
--space-xl: clamp(3.375rem, 3.2216rem + 0.6818vw, 3.75rem);
|
||||||
|
--space-2xl: clamp(4.5rem, 4.2955rem + 0.9091vw, 5rem);
|
||||||
|
--space-3xl: clamp(6.75rem, 6.4432rem + 1.3636vw, 7.5rem);
|
||||||
|
|
||||||
|
/* One-up pairs */
|
||||||
|
--space-3xs-2xs: clamp(0.3125rem, 0.1847rem + 0.5682vw, 0.625rem);
|
||||||
|
--space-2xs-xs: clamp(0.5625rem, 0.4091rem + 0.6818vw, 0.9375rem);
|
||||||
|
--space-xs-s: clamp(0.875rem, 0.7216rem + 0.6818vw, 1.25rem);
|
||||||
|
--space-s-m: clamp(1.125rem, 0.8182rem + 1.3636vw, 1.875rem);
|
||||||
|
--space-m-l: clamp(1.6875rem, 1.3551rem + 1.4773vw, 2.5rem);
|
||||||
|
--space-l-xl: clamp(2.25rem, 1.6364rem + 2.7273vw, 3.75rem);
|
||||||
|
--space-xl-2xl: clamp(3.375rem, 2.7102rem + 2.9545vw, 5rem);
|
||||||
|
--space-2xl-3xl: clamp(4.5rem, 3.2727rem + 5.4545vw, 7.5rem);
|
||||||
|
|
||||||
|
/* Custom pairs */
|
||||||
|
--space-s-l: clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem);
|
||||||
|
|
||||||
|
|
||||||
|
/*COLORS*/
|
||||||
|
--blue: #d7f0e1;
|
||||||
|
--darkblue: #2c6a88;
|
||||||
|
--oc-gray-3: #dee2e6;
|
||||||
|
--oc-gray-5: #adb5bd;
|
||||||
|
--oc-gray-6: #868e96;
|
||||||
|
--oc-gray-7: #495057;
|
||||||
|
--oc-gray-8: #343a40;
|
||||||
|
--oc-cyan-6: #15aabf;
|
||||||
|
--oc-cyan-9: #0b7285;
|
||||||
|
--oc-blue-1: #d0ebff;
|
||||||
|
--oc-blue-3: #74c0fc;
|
||||||
|
--oc-blue-4: #4dabf7;
|
||||||
|
--oc-blue-7: #1c7ed6;
|
||||||
|
--oc-blue-9: #1864ab;
|
||||||
|
--oc-grape-9: #862e9c;
|
||||||
|
--oc-violet-4: #9775fa;
|
||||||
|
--oc-violet-9: #5f3dc4;
|
||||||
|
|
||||||
|
}
|
||||||
body {
|
body {
|
||||||
font-family: "sans-serif";
|
font-family: "sans-serif";
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 66ch;
|
max-width: 66ch;
|
||||||
}
|
}
|
||||||
|
@layer translations {
|
||||||
|
body > trl-selector:first-child {display: none;} /* was adding a grid row! */
|
||||||
|
trl-selector {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: var(--space-3xs);
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: end;
|
||||||
|
justify-self: end;
|
||||||
|
align-items: start;
|
||||||
|
padding-inline: var(--space-3xs);
|
||||||
|
margin-inline-end: var(--space-3xs);
|
||||||
|
grid-column: grid-start/content-start;
|
||||||
|
align-self: start;
|
||||||
|
margin-top: var(--space-l);
|
||||||
|
background-color: var(--oc-blue-1);
|
||||||
|
max-width: max-content;
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
/* assumes labels follow their inputs immediately */
|
||||||
|
input:checked + label {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/* Do we use trl-selector ~ or [trl] descendants? */
|
||||||
|
/* need one of these rules for each language.*/
|
||||||
|
trl-selector:has(> input[value="nl"]:checked) {
|
||||||
|
& ~ trl-alt:lang('nl') {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
& ~ trl-alt:not(:lang('nl')) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trl-selector:has( > input[value="en"]:checked) {
|
||||||
|
& ~ trl-alt:lang('en') {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
& ~ trl-alt:not(:lang('en')) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body:has(> trl-selector input[value="nl"]:checked) {
|
||||||
|
& [trl-ui]:lang('nl') {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
& [trl-ui]:not(:lang('nl')) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
body:has(> trl-selector input[value="en"]:checked) {
|
||||||
|
& [trl-ui]:lang('en') {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
& [trl-ui]:not(:lang('en')) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,38 @@
|
||||||
import {fromHtml} from 'hast-util-from-html';
|
import {JSDOM} from 'jsdom';
|
||||||
import {toHtml} from 'hast-util-to-html';
|
|
||||||
import {visit} from 'unist-util-visit';
|
|
||||||
/*
|
/*
|
||||||
* The idea: need to create another subdir `title/nl/index.html`
|
* The idea: need to create another subdir `title/nl/index.html`
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* addTranslationInterface adds the <trl-selector> with radio buttons and labels to each <trl-group>.
|
||||||
|
* It sets the checked property on the indicated language.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* first, index.html is the original page, with the page language (from markdown frontmatter) active.
|
||||||
|
* This allows switching between languages for each translated fragment in the page.
|
||||||
|
* then, for each language in the frontmatter `trls`, another folder-with-index.html is generated,
|
||||||
|
* with <trl-selector> added,
|
||||||
|
* where the language corresponding to the given language is active.
|
||||||
|
*
|
||||||
|
* So note that page `trls: []` is independent of the languages of the `<trl-alt>`s in each `<trl-group>`.
|
||||||
|
*/
|
||||||
export default async (page) => {
|
export default async (page) => {
|
||||||
const html = await page.html;
|
const html = await page.html;
|
||||||
return {
|
return {
|
||||||
"index.html": page.html,
|
"index.html": addTranslationInterface(html, page?.lang),
|
||||||
...handleTranslations(html, page.trls)
|
...handleTranslations(html, page.trls)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//this is going to create a folder for each 'translation' specified in frontmatter.
|
||||||
function handleTranslations(html, trls) {
|
function handleTranslations(html, trls) {
|
||||||
if (trls) {
|
if (trls) {
|
||||||
|
console.log(trls);
|
||||||
const outputs = {};
|
const outputs = {};
|
||||||
trls.forEach(trl => {
|
trls.forEach(trl => {
|
||||||
outputs[trl] = {
|
outputs[trl] = {
|
||||||
"index.html": reorderTranslations(html, trl)
|
"index.html": addTranslationInterface(html, trl)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return outputs;
|
return outputs;
|
||||||
|
|
@ -27,11 +41,43 @@ function handleTranslations(html, trls) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//reorders all '.translation-group's so the element with given lang is first, and 'open' is set appropriately.
|
//"reorders" all `trl-group`s so the element with given lang is displayed.
|
||||||
//also, handles latest/laatst. Is that a special case, or should that be translated in the page too?
|
//EN is default language ...
|
||||||
function reorderTranslations(body, lang){
|
//also adds a (hidden by css) trl-selector at the top of `body`.
|
||||||
//handles both text and dom object as input
|
//TODO: add a link to translated pages ...
|
||||||
const hast = fromHtml(body);
|
//that's complicated, because what about all the links in the page?
|
||||||
//visit: trlselector>radio, and set active on current lang and inactive on other langs.
|
function addTranslationInterface(body, activelang="en"){
|
||||||
return toHtml(hast);
|
const dom = new JSDOM(body);
|
||||||
|
const doc = dom.window.document;
|
||||||
|
let seq = 1; //serial number for identifying translation group inputs and labels
|
||||||
|
const trlGroups = Array.from(doc.querySelectorAll('trl-group'));
|
||||||
|
trlGroups.forEach((trlGroup) => {
|
||||||
|
//for each trlGroup.
|
||||||
|
const trlAltElems = Array.from(trlGroup.querySelectorAll('trl-alt'));
|
||||||
|
const langsInGroup = trlAltElems.map(t => t.getAttribute('lang'));
|
||||||
|
const trlSel = doc.createElement('trl-selector');
|
||||||
|
langsInGroup.forEach(lang => {
|
||||||
|
console.log(lang);
|
||||||
|
let grname = `trlg-${seq}`;
|
||||||
|
let inputId = `${grname}-${lang}`;
|
||||||
|
const input = doc.createElement('input');
|
||||||
|
input.type = 'radio';
|
||||||
|
input.setAttribute('id', inputId);
|
||||||
|
input.setAttribute('name', grname);
|
||||||
|
input.setAttribute('lang', lang);
|
||||||
|
input.setAttribute('value', lang);
|
||||||
|
if (lang === activelang) {
|
||||||
|
input.setAttribute('checked', '');
|
||||||
|
}
|
||||||
|
const label = doc.createElement('label');
|
||||||
|
label.setAttribute('for', inputId);
|
||||||
|
label.textContent = lang;
|
||||||
|
trlSel.append(input);
|
||||||
|
trlSel.append(label);
|
||||||
|
|
||||||
|
})
|
||||||
|
trlGroup.prepend(trlSel);
|
||||||
|
seq ++; //increment id serial number
|
||||||
|
})
|
||||||
|
return dom.serialize();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,14 +64,9 @@
|
||||||
Then, we can use that html and the trls property to add the translations.
|
Then, we can use that html and the trls property to add the translations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//NOTE! two steps at once. Could separate the withTranslations part: add a html_LANG property to the document object, then later create the folder structure.
|
||||||
pagesInFolders: Tree.map(renderedPages, pagesInFoldersWithTranslations.js)
|
pagesInFolders: Tree.map(renderedPages, pagesInFoldersWithTranslations.js)
|
||||||
/*
|
|
||||||
pagesInFolders: Tree.map(renderedPages, {
|
|
||||||
value: (value) => {
|
|
||||||
index.html: value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
|
|
||||||
//bug in 0.6.14?
|
//bug in 0.6.14?
|
||||||
linksByFile: Tree.map(renderedPages,getLinkedFilesFromHtml.js)
|
linksByFile: Tree.map(renderedPages,getLinkedFilesFromHtml.js)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue