doxa-maps/plugin-designs/key-cities/city-poster-wall.vue
Doxa Maps a4622781a2 Key Cities: all nine region headings read in the page's language, and the region stays the key
This corrects my own "Other" fix (9d12e59b6), which could never fire. gospel's cities-internet analysis (87a168195) showed the same shape here: key-cities.json has no row with an empty region (1,646 rows), "Other" (2) and "N/A" (19) are region VALUES, and every section heading printed its raw English data string in every locale. The fallback I translated also put a label into the grouping key.

Now, as in cities-internet: the raw region string stays the grouping key (sections, :key, collapse state), with 'Other' as the data guard; the heading is projected at render by regionLabel.js from the keys the data's strings already are the English values of (dashboard.wagfRegion.*, dashboard.other, wall.na), written out in full so the build ships those areas. The poster wall, whose PosterWall prints its section name as given, groups by that projected heading, as country-posters' wall does. keyCities.posters.otherRegion is no longer used.

Headless (_qa-cycle/exp-shepherd/check-keycities-regions.mjs): every one of the nine region values maps to its catalogue heading in ar, zh, es and ru, and an unknown value passes through as data. key-cities is gated, so nothing in public/ changes.
2026-09-29 13:14:46 +00:00

76 lines
3.1 KiB
Vue

<script setup>
/**
* city-poster-wall.vue — the KEY CITY POSTER WALL.
*
* One poster per named population centre, grouped by region and collapsible —
* rendered by the SHARED @map/components/poster/PosterWall.vue, the same component
* the 100-list and country walls use. Third consumer, zero new wall code: that is
* the payoff of promoting it to the library rather than copying it per app.
*
* WHY 176 AND NOT 1,646. A sheet is generated only where all three hold:
* NAMED — by a cited gazetteer (Nominatim/OSM). An unnamed cluster would
* make a poster titled "unnamed location", which is not a poster.
* MULTI-GROUP — >1 people group within ~25km. A single centroid is a pin, not
* a population centre.
* ASCII-SAFE — the sheet fonts are Lato/Georgia. 99 of the 277 named centres are
* non-Latin (Hebrew/Arabic/Lao/Tibetan/Chinese/Cyrillic) and would
* render as tofu, so they are HELD on the the brief's font decision
* (likely Noto Sans per-script) rather than shipped broken.
* Partial and correct beats complete and wrong. The wall shows only what exists.
*/
import { computed, inject, ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { regionLabel } from './regionLabel.js'
import PosterWall from '@map/components/poster/PosterWall.vue'
import { resolveAssetsBase } from '@map/utils/embedBase.js'
const profileConfig = inject('profileConfig', ref(null))
const isDark = computed(() => profileConfig.value?.isDark === true)
const assetsBase = computed(() => resolveAssetsBase(profileConfig.value))
const rows = ref([])
onMounted(async () => {
try {
const r = await fetch(`${assetsBase.value}/tables/key-cities.json`)
if (r.ok) rows.value = (await r.json()).rows || []
} catch (_) { /* the wall renders empty rather than throwing */ }
})
// Only rows that actually HAVE a sheet. poster_id is set by the table builder, so
// the wall never asks for an image that was never generated.
const items = computed(() => rows.value
.filter((r) => r.poster_id)
.map((r) => ({
id: r.poster_id,
label: r.place_name,
count: r.people_group_count,
region: r.region,
bbox: null,
})))
const { t } = useI18n()
// PosterWall prints its section name as given, so the wall groups by the region's heading in the page's
// language (as country-posters' wall does). 'Other' is the data guard dashboard.other projects.
const groupBy = (c) => regionLabel(t, c.region || 'Other')
const collapsedBy = (sec) => sec.total < 20
</script>
<template>
<PosterWall
:items="items"
:group-by="groupBy"
:is-dark="isDark"
:assets-base="assetsBase"
event-name="doxa-key-cities:show-on-map"
:heading="$t('keyCities.posters.heading')"
:tag="$t('keyCities.posters.tag')"
:intro="$t('keyCities.posters.intro')"
unit="UPG"
:item-noun="$t('keyCities.posters.itemNoun')"
:item-noun-plural="$t('keyCities.posters.itemNounPlural')"
:collapsible="true"
:collapsed-by="collapsedBy"
:prayer-list-soon-message="$t('keyCities.posters.soon')"
download-prefix="doxa-city"
/>
</template>