Suppose you have an ESP32 and you need to make a professional product with it.
The first interface the final user will see will be the WIFI configuration page.
How do you serve such webpage so it's as small as possible yet professional ?
A single file webpage
Since the flash size in the ESP32 is limited and you probably want to use Over-The-Air (OTA), your assets must be very small.
It's not realistic to use jQuery or any other large javascript library (which you can't serve from outside your ESP32 because it's not connected to the internet yet).
So, you're limited to HTML + CSS and probably some super minimal javascript.
Typically, you might want a functional website without javascript since that might be disabled on the browser.
So next, how do you deal with multiple languages for your webpage ?
You could have as many webpages as you are supporting different languages and use the Accept-Language
HTTP's header to decide which one to serve, but this means that your website's page is duplicated for all different languages.
This is not acceptable in space limited device like ESP32.
There are Javascript based solutions, like Polyglot that requires you store a JSON with all translations and then AJAX load them and apply the changes.
Theses solutions are, IMHO, ugly since you'd get a page that'll load with one language and then flash to another language. It's a bit like the FOUC we had with CSS.
They also fails if the user does not allow javascript.
The technic I'm showing here is based on CSS only (less likely to be disabled).
The HTML markup
The basic idea for this technic is to store any translatable text in <var></var>
elements. These elements are sparsely used on the web but they are part of HTML specification since version 4.
They are unlikely to appear anywhere, so dedicating them for translation seems like a good idea.
Please notice that you'll need to add var { font-style: normal }
to your main style.
You'll store the elements with either an id
set (like <var id='title'>Title here in English</var>
) if they are unique, or a class if not.
So, for example, your HTML markup will look like:
<body>
<h1><var id='title'>My wonderful project</var></h1>
<ul>
<li><var id='MenuItem1'>Setup</var></li>
<li><var id='MenuItem2'>Firmware download</var></li>
</ul>
<div><a href='aboutUs'><var class='aboutUs'>About us</var></a>
[etc...]
The CSS
This is were the trick is going. There is no -non javascript- way to trigger the lang of the document automatically.
This means that either you set <html lang='fr'>
for the root element and then you can select on this in the CSS, but you can't, as far as I'm aware of, remove the attribute and have different :lang(fr)
selector working in your CSS.
However, the browser will send an Accept-Language
header withing the HTTP request, so we can still solve this server side by returning a different content based on the queried language.
Typically, in the embedded CSS in your webpage, you'll add a @import 'trans.css';
at the top (or use the longer <link>
node in the header), but since we want to save space the former is smaller & better.
Then, your webserver in the ESP32 will send a specific trans.css
file based on the browser's accepted language.
Typically, it'll send nothing for english (since it's the default language), but for another language, it'll send something like:
@charset 'utf-8';
var { visibility: hidden; } var:before { visibility: visible; } // Or any other content substitution technic
#title:before { content:'Titre attendu'; }
#MenuItem1:before { content:'Installation'; }
#MenuItem2:before { content:'Téléchargement du firmware'; }
var.aboutUs:before { content:'À propos'; }
The browser will automatically download this CSS and will replace the elements.
This method does not work with screen readers that'll still read the english text, but neither does the javascript version.
Overhead
This method does not require Javascript.
Because you use a single web page, and most browsers emit 2 requests in parallel, it should download the translation before the main web page, so no FOUC to expect.
This method requires a translation table that's written in CSS, thus the overhead is a bit larger than a JSON's dictionary object.
Typically, for each key to translate, you'll have an overhead of 18 bytes (or 17 if using :after
), before compression. Since the overhead is mainly due to same CSS terms :before
and content:
, they'll compress darn well via gzip and you can serve them directly compressed.
Drawbacks
- The elements that can't contain other elements (
inline
) should not contain<var>
either. So you'll have to take this into account when designing your website. - The
<var>
initial content is still here (but not visible) so it'll be used by screen readers, and search indexer. Since the webpage is unlikely to be served on the main internet, I'm not sure it's a big loss. - Everyone says that CSS is not for the updating the content, but honestly, why did they add
content
rule then ?
Hope it helps someone!
@xryl669, I gave you a vote!
If you follow me, I will also follow you in return!
Enjoy some !popcorn courtesy of @nextgencrypto!
Congratulations @xryl669! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :
Award for the number of upvotes received
Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word
STOP
Do not miss the last post from @steemitboard:
Congratulations @xryl669! You received a personal award!
Click here to view your Board of Honor