Skip to content

Localization and Themes

Mikhail Deynekin edited this page Oct 16, 2026 · 1 revision

Localization and Themes

TrayIconGuard ships 30 locales and a Fluent 2026 design system implemented by hand in GDI+: solid themed surfaces, eight accent presets, live Windows theme following, and typographic tokens that probe for Segoe UI Variable at runtime. This page documents both systems as implemented at commit 124e849, including the coverage tiers and the one acknowledged gap (right-to-left mirroring).


Contents


Locale registry and fallback

String ids live in an enum (src/ui/lang/strings.h, ~230 ids). The English base table is complete and ordered; each other locale is a sparse, id-tagged pack compiled from lang_<code>.cpp via the TIG_E(Id, L"…") macro (langdef.h) — order-independent and link-safe. At runtime l10n::t(id) returns the current locale's entry or the English string for that id when the pack does not carry it: untranslated ids degrade to English per string, never to blank space.

Coverage tiers

Tier Locales Coverage
Base en complete (definition)
Complete ru all ids (measured 231 TIG_E entries)
Core UI (~150 ids) zh es de fr pt ja ko it measured e.g. zh 151 entries
Essential (45–75 ids) hi ar bn ur id tr ko vi th pl nl uk fa el cs sv hu ro he fi da measured e.g. da 45 entries

Full ordered list (by worldwide prevalence, English first): en, zh, hi, es, ar, fr, bn, ru, pt, ur, id, de, ja, tr, ko, vi, it, th, pl, nl, uk, fa, el, cs, sv, hu, ro, he, fi, da.

Note

Right-to-left locales (ar, he, fa, ur) are translated but rendered in a left-to-right layout: mirroring is a tracked future item, stated in docs/I18N.md. Placeholder integrity (%s, %d) and product names (TrayIconGuard, Windows, Explorer, EnableAutoTray…) are contributor rules.

Selection and auto-detect

  • Setting appearance.language: "auto" (default) or a BCP-47 primary tag; legacy "ru" and "en" values still load.
  • "auto" resolves through GetUserDefaultUILanguage()'s primary language against a 29-case map in src/core/os.cpp; unmapped OS languages fall back to en.
  • Live switching: Appearance → Language list (native endonyms + English names + code, “Auto” row on top, check mark on the configured value). No restart; every built page relabels immediately.

Adding or improving a locale

  1. Copy an existing lang_xx.cpp, rename, fill TIG_E entries (ids from strings.h).
  2. Register: extern const LangTable kTable_xx; plus the registry entry in strings.cpp, the OS-language mapping in core/os.cpp, and native/English names in the macro tail.
  3. Build and screenshot-verify: set "language":"xx" and run --ui-test dashboard.

Themes: Light, Dark, System

ThemeMode = System (0) / Light (1) / Dark (2), stored in appearance.theme. System resolves against HKCU\…\Themes\Personalize\AppsUseLightTheme and re-resolves live on WM_SETTINGCHANGE("ImmersiveColorSet"). The top-bar sun/moon button cycles Light → Dark → System from any page. On Windows 11 the frame follows suit via DWMWA_USE_IMMERSIVE_DARK_MODE; on Windows 10 the dark frame needs 1809+, earlier builds keep a light frame around a themed client area. Backgrounds are solid palettes, not Mica — a deliberate stability decision recorded in the project's design notes.

Accents

appearance.accent = "system" (Windows colorization color via DWM\ColorizationColor, falling back to DwmGetColorizationColor, finally #0F6CBD) or one of eight presets:

Preset Hex
Windows blue #0F6CBD
Violet #744DA9
Teal #0E7070
Green #0F7B0F
Rust #98450C
Orchid #C239B3
Crimson #9A0021
Graphite #4C5B66

Hover/pressed variants are derived by mixing 10–20 % toward white/black.

Design tokens

Resolved per theme by src/ui/theme.cpp (values from docs/DESIGN.md, matching code):

Token Light Dark
window background #F3F3F3 #202020
card background #FBFBFB #2B2B2B
card border #E5E5E5 #3A3A3A
text primary / secondary / disabled #1B1B1B / #5D5D5D / #9E9E9E #FFFFFF / #C5C5C5 / #8A8A8A
success / warning / danger #0F7B0F / #9D5D00 / #C42B1C #6CCB5F / #FCE100 / #FF99A4
scrollbar / status bar #C4C4C4 / #EBEBEB #5A5A5A / #1B1B1B

Geometry: 4-px grid; card radius 8, control radius 4; nav rail 244/64 px with 44 px items; top bar 92, status bar 30; content padding 28; rows 56 (40 compact); toggles 40×20; buttons 32 high; overlay scrollbars 6 px.

Typography and glyphs

Family probe: Segoe UI Variable Text at runtime (GetTextFaceW), fallback Segoe UI. Sizes at 96 dpi: page title 26 semibold, card title 14 semibold, body 14, secondary 11.5–12.5, stat value 18, log text Cascadia Mono → Consolas 11.5. Iconography uses Segoe Fluent Icons with fallback Segoe MDL2 Assets (documented codepoint map in docs/DESIGN.md); environments without either font — Wine, stripped VMs — show glyph boxes while layout remains correct.

Motion

Exponential-approach easing: toggle knob+color 160 ms, segmented pill 180 ms, hover/press 90–140 ms. A 16 ms timer runs only while something is animating; animations: false freezes every widget at its target value and the timer never arms.


See also

Clone this wiki locally