The five are NOT one shape, and treating them as one would have changed what readers see. Measured before touching them: ApproxPinNote, FilterDropdown fall back to a literal map SemanticTreeLegend, PosterWall fall back to humanizeKey() — 'legend.columns.name' renders 'Name' PinHint falls back to a one-key map SemanticTreeLegend, PinHint also capture i18n.te (used 3x and 1x) PosterWall also captures i18n.locale So useOptionalT grew an optional `fallback` hook, and useOptionalI18n was added for the callers that need te and locale. Every site passes the fallback it already had, so not one rendered string changes. Routing them through the catalogue instead would have altered what seven bare-host bundles print, and — because tStatic honours the runtime locale — would have started translating strings that are English today. That may be an improvement; it is not this commit's to make. Changing a default is not a migration. te keeps its existing contract too: FALSE on a bare host, never "true because the catalogue has it". PinHint and SemanticTreeLegend both record why — te is how their callers know to use their own defaults. THE CHECK NOW LIVES ON MAIN, which is the point of this commit as much as the migration is. dx-shepherd: the 18-assertion version was in _qa-cycle, so it would never have run again. internal/check-optional-t-equivalence.mjs is registered as check:optional-t-equivalence — script line, //scripts note and gates:post token, all inserted by hand rather than by re-serialising package.json. It carries 46 assertions: the helper's contract across all three host states, a branch-for- branch equivalence against the old hand-written code, and a PER-SITE REGISTER that every later C4 wave appends a row to. Negative-tested from outside: strip one site's own fallback and it fails naming that site. check:library-index went red on the new composable and is green again after `bun run library-index`. That is the staleness gate working, not a flake.
38 lines
2.2 KiB
Vue
38 lines
2.2 KiB
Vue
<!--
|
|
ApproxPinNote.vue — the ONE wording every map with people-group pins uses (APPROXPIN, 2026-09-26).
|
|
|
|
The first sentence always: a dot is where a people is found, not a town or a boundary. The second only
|
|
when the pin's point is SHARED, naming the other groups (from library/utils/colocation.js, built from the
|
|
roster the map draws), because "approximate" alone hides that some dots are the same dot.
|
|
Never shows the raw coordinate: six decimal places beside a caveat that says "approximate" reads as a
|
|
contradiction. Wording: gospel-plugin's measured proposal (P5), in library/i18n/locales/<lc>/pins.json.
|
|
-->
|
|
<script setup>
|
|
import { computed } from 'vue'
|
|
import { useOptionalT } from '@map/composables/useOptionalT.js'
|
|
|
|
const props = defineProps({
|
|
/** Names of the OTHER groups on this pin's coordinate; empty = not shared. */
|
|
shared: { type: Array, default: () => [] },
|
|
dark: { type: Boolean, default: false },
|
|
})
|
|
// i18n is OPTIONAL here, as in PinHint: an unguarded useI18n() throws on a host that never installed
|
|
// vue-i18n, inside the custom-element boundary, and the reader gets an empty shadow root. Without it
|
|
// the English below renders, with the same placeholders filled.
|
|
const APPROX_FALLBACK = {
|
|
'pins.approximate': 'The dot marks where this people is found, not a town or a boundary.',
|
|
'pins.sharedPoint': 'It sits on the same point as {names} — {n} groups share this coordinate, so the position tells you the locality and not which group is where.',
|
|
}
|
|
// C4: the guard is library/composables/useOptionalT.js now. The fallback MAP stays exactly as it was,
|
|
// passed in, so a bare host renders the same English it rendered before.
|
|
const t = useOptionalT('', { fallback: (key) => APPROX_FALLBACK[key] })
|
|
const second = computed(() => props.shared.length
|
|
? t('pins.sharedPoint', { names: props.shared.join(', '), n: props.shared.length + 1 })
|
|
: '')
|
|
</script>
|
|
|
|
<template>
|
|
<p class="approx-pin-note" :style="{ margin: '6px 10px 4px', font: '400 11px/1.4 system-ui, -apple-system, Segoe UI, Roboto, sans-serif', color: dark ? 'rgba(243,243,241,0.7)' : '#5b6470' }">
|
|
{{ t('pins.approximate') }}<template v-if="second"> {{ second }}</template>
|
|
</p>
|
|
</template>
|