diff --git a/plugin-designs/posterverse/posterverse.vue b/plugin-designs/posterverse/posterverse.vue index 0e2100807..ccb34e9c7 100644 --- a/plugin-designs/posterverse/posterverse.vue +++ b/plugin-designs/posterverse/posterverse.vue @@ -57,6 +57,11 @@ + + + + @@ -66,6 +71,8 @@ import { defineComponent, inject } from 'vue' import VerticalTabsLayout from '@map/layouts/VerticalTabsLayout.vue' import BackToTopButton from '@map/components/BackToTopButton.vue' +import ShellLanguageMenu from '@map/components/ShellLanguageMenu.vue' +import { saveLocale } from '@map/layouts/app-wrapper-material/languages.js' import { loadScriptOnce, whenTagDefined } from '@map/utils/embedScript.js' import { translate, LOCALES } from './src/strings.js' import { SECTIONS, TABS, resolveTabs } from './src/tabs.js' @@ -93,7 +100,7 @@ export default defineComponent({ // The host's attributes stay on the host: an inline style copied onto the layout root beats the // layout's own rules (a styled host once collapsed a nested map to 76px). inheritAttrs: false, - components: { VerticalTabsLayout, BackToTopButton }, + components: { VerticalTabsLayout, BackToTopButton, ShellLanguageMenu }, props: { treeBase: { type: String, default: '' }, profileConfig: { type: [String, Object], default: '' }, @@ -128,6 +135,11 @@ export default defineComponent({ // The manifest's `runtime` block (the build's apiBaseUrl + public token), for foreign-page embeds. runtime: {}, hostLang: detectHostLocale(), + // A language picked in THIS session through the menu, and the host's language value it was picked + // over. The pick wins only while that value is unchanged; the saved choice (loadLocale) is never + // read, since it falls back to the browser's language and would override the host page. + localPick: '', + pickBase: null, // Until the manifest lands, the rail shows the rows that are expected to exist; provisional rows // appear only once the manifest proves their bundle is in this tree. tabs: TABS.filter((d) => !d.provisional).map(freshTab), @@ -153,10 +165,13 @@ export default defineComponent({ return this.manifestBase ? this.manifestBase.replace(/\/+$/, '') + '/assets' : '' }, headingText() { return String(this.cfg.heading || this.heading || '').trim() || 'Posterverse' }, - // Language precedence: what the host says, then the host page's own language, then English. + // The language the host passed: the `language` prop, else profile-config language / locale / lang. + hostLanguage() { return String(this.language || this.cfg.language || this.cfg.locale || this.cfg.lang || '').trim() }, + // Language precedence: this session's menu pick (while the host's value is the one it was made over), + // then what the host says, then the host page's own language, then English. effectiveLocale() { - const fromProp = String(this.language || this.cfg.language || this.cfg.locale || this.cfg.lang || '').trim() - return (fromProp || this.hostLang || 'en').split('-')[0].toLowerCase() + if (this.localPick && this.hostLanguage === this.pickBase) return this.localPick + return (this.hostLanguage || this.hostLang || 'en').split('-')[0].toLowerCase() }, uiLocale() { return LOCALES.includes(this.effectiveLocale) ? this.effectiveLocale : 'en' }, uiDir() { return this.uiLocale === 'ar' ? 'rtl' : 'ltr' }, @@ -201,6 +216,8 @@ export default defineComponent({ this.mountElement(this.activeIndex) }, tab(id) { if (id) this.onSelect(id) }, + // A host that sets a new language takes over again: the session pick is dropped. + hostLanguage(v) { if (v !== this.pickBase) { this.localPick = ''; this.pickBase = null } }, }, mounted() { this.watchHostLang() @@ -213,6 +230,12 @@ export default defineComponent({ }, methods: { tr(key, params) { return translate(this.uiLocale, key, params) }, + // The menu's 'switch': no host cancelled the request, so the shell switches itself. + setLocale(code) { + this.pickBase = this.hostLanguage + this.localPick = code + saveLocale(code) + }, tabLabel(t) { return this.tr('tab.' + t.id) }, tabSub(t) { return t.section === 'experimental' ? this.tr('experimentalSub') : this.tr('sub.' + t.id) }, setSlot(i, el) { if (el) this._slots = Object.assign(this._slots || {}, { [i]: el }) },