1a0197812d
Build and Deploy Verso / deploy (push) Successful in 14m53s
Users can now select their UI language directly without relying on subdomain routing (fr.verso.alocoq.fr etc.). Resolution order: (1) verso-lang cookie, (2) subdomain host header, (3) OVERLEAF_SITE_LANGUAGE default — fully backward compatible. Changes: - Translations.mjs: read verso-lang cookie in middleware; include all bundled locale files in availableLanguageCodes regardless of subdomain config so every loaded locale appears in the picker - User.mjs: add languageCode field to persist preference per user - UserController.mjs: setLanguage handler — sets cookie (1 year) and writes languageCode to DB when called by a logged-in user - AuthenticationController.mjs: on login, sync DB languageCode to cookie so preference follows the user to any new browser/device after login - ExpressLocals.mjs: expose availableLanguages to all Pug templates - router.mjs: GET /set-language?lng=<code> (anonymous + logged-in), POST /user/language (logged-in, REST-style) - language-picker.pug: replace subdomain href links with /set-language redirect links; iterate availableLanguages instead of subdomainLang - thin-footer.pug: show picker whenever availableLanguages.length > 1, not only when multiple subdomains are configured Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
36 lines
1.1 KiB
Plaintext
36 lines
1.1 KiB
Plaintext
include ../_mixins/material_symbol
|
|
|
|
li.dropdown.dropup.subdued.language-picker(dropdown)
|
|
button#language-picker-toggle.btn.btn-link.btn-inline-link(
|
|
dropdown-toggle
|
|
data-ol-lang-selector-tooltip
|
|
data-bs-toggle='dropdown'
|
|
aria-haspopup='true'
|
|
aria-expanded='false'
|
|
aria-label='Select ' + translate('language')
|
|
tooltip=translate('language')
|
|
title=translate('language')
|
|
)
|
|
+material-symbol('translate')
|
|
|
|
|
span.language-picker-text #{settings.translatedLanguages[currentLngCode] || currentLngCode}
|
|
|
|
ul.dropdown-menu.dropdown-menu-sm-width(
|
|
role='menu'
|
|
aria-labelledby='language-picker-toggle'
|
|
)
|
|
li.dropdown-header #{translate("language")}
|
|
each lngCode in availableLanguages
|
|
if settings.translatedLanguages[lngCode]
|
|
- let isActive = lngCode === currentLngCode
|
|
li.lng-option
|
|
a.menu-indent(
|
|
href='/set-language?lng=' + lngCode
|
|
role='menuitem'
|
|
class=['dropdown-item', {active: isActive}]
|
|
aria-selected=isActive ? 'true' : 'false'
|
|
)
|
|
| #{settings.translatedLanguages[lngCode]}
|
|
if isActive
|
|
+material-symbol('check', 'dropdown-item-trailing-icon')
|