Skip to content

About

The best website for MultiCrafters.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

516 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MultiCraft-Info

A website with informations about the MultiCraft game.

Website

Developed with HTML/CSS/JS

Features

* Displays the list of physical servers
* Displays the list of game servers
* Displays the list of updates
* Allows users to put reviews for servers
* Chat with others user
And other great features coming soon!

Themes

The gear button in the header opens the appearance settings:

material.css   Material Design 3 layer, loaded after style.css
js/theme.js    the settings: menus, accent colour, Material palette generation

Three settings, all stored per device in localStorage:

key values meaning
mc_theme normal, material overall look of the site
mc_scheme auto, light, dark, amoled Material background
mc_accent green, teal, blue, violet, … seed colour of the palette

normal is the default look and is left completely untouched: every rule in material.css is prefixed with html.theme-material. The choice is applied by putting that class and a data-scheme attribute on <html>; a small inline script in <head> does it before the first render, so there is no flash of the wrong theme.

The colours are computed, not hard-coded. The accent colour is turned into a real Material 3 tonal palette by @material/material-color-utilities — the official library Material Web itself uses — and the result is written to <html> as --md-sys-color-* custom properties, which is the contract documented for theming Material Web components. material.css maps those tokens onto the site's own CSS variables, so a new accent recolours the whole site at once. The generated palette is cached in mc_theme_tokens and reapplied inline at page load; if the CDN cannot be reached (offline, blocked), material.css falls back to static Material palettes, one per background, and everything still works.

amoled is the same dark palette with true-black surfaces (#000), for OLED screens.

Material Web components are loaded from https://esm.run through an import map, and used where they replace hand-written markup one-for-one: md-switch for the profile setting and md-circular-progress for every loading indicator. They are optional: if the CDN fails, md-circular-progress:not(:defined) falls back to a plain CSS spinner and the rest of the site behaves identically.

From the console: Theme.set('material'), Theme.setScheme('amoled'), Theme.setAccent('violet'), Theme.get().

Internationalisation (i18n)

The site is translated with plain JSON files — no framework, no dependency. Two places only:

locales/*.json   one file per language (en.json is the reference file)
i18n.js          the engine: loads a file, applies it to the DOM, renders the switcher
locales/fr.json   Français          locales/zh.json   中文
locales/en.json   English (ref.)    locales/ja.json   日本語
locales/es.json   Español           locales/ko.json   한국어
locales/de.json   Deutsch           locales/hi.json   हिन्दी
locales/pt.json   Português         locales/bn.json   বাংলা
locales/nl.json   Nederlands        locales/ar.json   العربية
locales/ru.json   Русский           locales/id.json   Bahasa Indonesia
locales/uk.json   Українська        locales/tr.json   Türkçe
locales/br.json   Brezhoneg         locales/nrm.json  Cauchois

Every language shows a flag image in the switcher, loaded from /flags/<code>.svg (see FLAGS_PATH in i18n.js): the emoji kept in LANGUAGES is now only a fallback when an image is missing, which also covers Breton and Norman since those flags have no Unicode emoji. All flags come from Wikimedia Commons and are in the public domain — sources, licences and local changes are listed in flags/README.md. A file named differently can be pointed at with flagImg: '/flags/other.svg'. Language codes may be two or three letters (br, nrm).

The update posts themselves only exist in French (post.md) and English (post-en.md). On every other language, the updates page therefore shows the notice updates.langNotice ("only available in English and French"), displayed by CSS from the <html lang> attribute — see .updates-lang-notice in style.css.

How a language is chosen

  1. URL prefix (/ja/serveurs, /pt-BR/…) — wins over everything, so a shared link keeps its language. French is the site default and has no prefix.
  2. Remembered choice — stored in localStorage (mc_lang).
  3. Browser language — detected on the first visit (pt-BR → Brazilian Portuguese, es-MX → Mexican Spanish, es-AR → Spanish, zh-TW → Chinese…).
  4. French if nothing matches.

The switcher in the header is a single button showing the current flag; clicking it opens a dropdown that lists every language with its flag and native name. Both are generated from the LANGUAGES list in i18n.js, so the HTML never needs to change.

Add a new language (e.g. Italian)

1. Copy locales/en.json to locales/it.json
2. Translate the values (never the keys)
3. Add one line to LANGUAGES in i18n.js:
     { code: 'it', flag: '🇮🇹', name: 'Italiano' }
4. Run `node scripts/check-i18n.js` and test the language switcher in the browser

That single line drives the switcher button, the menu entry, the URL prefix, the browser detection and the <html lang> attribute. A regional variant that reuses an existing translation file just adds file: '<code>' (see es-MX and pt-BR in i18n.js).

script.js re-renders dynamic content on its own when the language changes (it listens to the langchange event).

Add a new translation in the HTML

Use an attribute, then add the key to both locales/fr.json and locales/en.json:

<span data-i18n="home.example"></span>           <!-- text -->
<h1 data-i18n-html="home.title"></h1>             <!-- text containing HTML -->
<input data-i18n-placeholder="servers.searchPlaceholder">
<button data-i18n-title="ui.example">
<button data-i18n-aria-label="modal.close">
<meta data-i18n-content="meta.description">
"home.example": "…"

Translations from JavaScript

t() is available everywhere (dynamic content, modals, counters, notifications…):

t('servers.count1');                        // → "serveur"
t('modal.playerOnlineN', { count: 12 });    // → { count } is replaced when given
window.i18n.lang;                           // → 'fr' | 'en' | 'ja' | 'pt-BR' …
window.i18n.loc('Singapour');               // → translates a location name
window.i18n.isLang('ja');                   // → true if 'ja' is a supported language prefix
window.setLang('ja');                       // → switch language (persists the choice)
await window.i18n.ready;                    // → translations of the current language loaded
window.i18n.apply();                        // → re-applies translations to the DOM

If a key is missing, the engine logs [i18n] clé inconnue : « … » in the console and keeps the key as-is; the HTML element keeps its existing content.

Validate translations

node scripts/check-i18n.js

It reports keys present in one language but missing in the other, and keys used in the HTML/JS but absent from the locale files. Development tool only — the site never needs it.

Note: netlify/edge-functions/meta.js (link previews read by Discord/X before any JavaScript runs) keeps its own LANG_CODES list and French/English strings. When adding a language, add its code there too — otherwise its URL prefix is not recognized and its preview falls back to English.

Licenses

License for the code : GNU General Public License V3
License for text and pictures in "updates" directory : CC-BY-NC 4.0
License of MultiCraft Font : CC-BY-SA 3.0 (Copyright MultiCraft Studio OÜ)

(C) Deblock Studios 2026

About

The best website for MultiCrafters.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages