diff --git a/plugin-designs/posterverse/scripts/check-posterverse-shelf.mjs b/plugin-designs/posterverse/scripts/check-posterverse-shelf.mjs index de21094f8..957f89670 100644 --- a/plugin-designs/posterverse/scripts/check-posterverse-shelf.mjs +++ b/plugin-designs/posterverse/scripts/check-posterverse-shelf.mjs @@ -20,6 +20,7 @@ * D. posterverse.meta.json `composes` == the bundle/profile of every row whose bundle exists in * plugin-designs/ (two-sided: nothing declared that the rail cannot show, nothing shown undeclared). * E. strings: every locale carries every English key, and every key the shell reads exists in English. + * F. a rail label named in LABEL_FOLLOWS equals that plugin's own catalogue title, in every locale. * * Headless, no browser. Exit 0 pass · 1 fail · 75 not measured (no built manifest). */ @@ -40,10 +41,14 @@ const GATED = 'key-cities' // Rows whose plugin is a natural-height page: mounted unpinned so the pane scrolls them. Named, because a // pinned scroll page traps its own content and nothing else would notice. const EXPECT_SCROLL = ['bless-india-posters'] +// Rail labels that must EQUAL the plugin's own title (vocabulary follows the plugin), per locale: +// row id -> [catalogue area file under library/i18n/locales//, key inside it]. Copied, not read at +// runtime: naming the area from the shell would ship the plugin's whole catalogue inside posterverse.js. +const LABEL_FOLLOWS = { 'bless-india-posters': ['blessIndiaPosters.json', 'title'] } const sameList = (a, b) => a.length === b.length && a.every((x, i) => x === b[i]) -export function checkShelf({ SECTIONS, TABS, NEVER, resolveTabs, manifest, meta, bundleExists, STRINGS }) { +export function checkShelf({ SECTIONS, TABS, NEVER, resolveTabs, manifest, meta, bundleExists, STRINGS, pluginTitles = {} }) { const errs = [] const notes = [] // A. exact membership, per section, in order @@ -104,6 +109,14 @@ export function checkShelf({ SECTIONS, TABS, NEVER, resolveTabs, manifest, meta, const v = STRINGS[l][k] if (typeof v !== 'string' || !v.trim()) errs.push(`E: ${l} is missing "${k}"`) } + // F. labels that follow a plugin's own title, per locale + for (const [id, byLocale] of Object.entries(pluginTitles)) { + for (const [l, want] of Object.entries(byLocale)) { + const got = (STRINGS[l] || {})['tab.' + id] + if (want === undefined) errs.push(`F: ${l}: the plugin's own title for ${id} is missing from its catalogue`) + else if (got !== want) errs.push(`F: ${l}: tab.${id} is ${JSON.stringify(got)}, the plugin's own title is ${JSON.stringify(want)}`) + } + } return { errs, notes, counts: { rows: TABS.length, resolved: resolved.length, composes: composes.length, locales: locales.length, keys: Object.keys(en).length } } } @@ -115,7 +128,17 @@ async function load() { const mf = join(ROOT, 'public', TREE_NAME, 'manifest.json') const manifest = existsSync(mf) ? JSON.parse(readFileSync(mf, 'utf8')) : null const bundleExists = (b, p) => existsSync(join(ROOT, 'plugin-designs', b, `${p}.vue`)) - return { ...tabs, STRINGS, meta, manifest, bundleExists } + const pluginTitles = {} + for (const [id, [file, key]] of Object.entries(LABEL_FOLLOWS)) { + pluginTitles[id] = {} + for (const l of Object.keys(STRINGS)) { + const f = join(ROOT, 'library/i18n/locales', l, file) + let v + try { const j = JSON.parse(readFileSync(f, 'utf8')); v = key.split('.').reduce((o, k) => (o == null ? o : o[k]), j) } catch { v = undefined } + pluginTitles[id][l] = v + } + } + return { ...tabs, STRINGS, meta, manifest, bundleExists, pluginTitles } } function selfTest(base) { @@ -130,6 +153,7 @@ function selfTest(base) { ['C: a composite row falls back to a leaf', (c) => { c.manifest = clone(c.manifest); const b = c.manifest.bundles.find((x) => x.bundle === 'my-upg-100-list'); b.profiles = b.profiles.filter((p) => p.profile !== 'upg-100-mfe') }, /^C: row upg-100 opens/], ['D: composes drift', (c) => { c.meta = { ...c.meta, composes: c.meta.composes.slice(1) } }, /^D: the rail shows/], ['D: composes a ref the rail cannot show', (c) => { c.meta = { ...c.meta, composes: [...c.meta.composes, 'key-cities/key-cities'] } }, /^D: meta composes/], + ['F: a rail label drifts from the plugin title', (c) => { c.STRINGS = clone(c.STRINGS); c.STRINGS.ar['tab.bless-india-posters'] = 'باركوا الهند: ملصقات' }, /^F: ar: tab\.bless-india-posters is/], ['E: a locale loses a key', (c) => { c.STRINGS = clone(c.STRINGS); delete c.STRINGS.ar['tab.upg-100'] }, /^E: ar is missing "tab.upg-100"/], ['E: a row without an English label', (c) => { c.STRINGS = clone(c.STRINGS); delete c.STRINGS.en['tab.bible-posters'] }, /^E: the shell reads "tab.bible-posters"/], ] diff --git a/plugin-designs/posterverse/src/strings.js b/plugin-designs/posterverse/src/strings.js index 1456e526a..c2c31c12c 100644 --- a/plugin-designs/posterverse/src/strings.js +++ b/plugin-designs/posterverse/src/strings.js @@ -35,7 +35,7 @@ export const STRINGS = { 'tab.poster-design': 'Diseño de carteles', 'sub.poster-design': 'todos los estilos y tamaños de cartel', 'tab.wall-of-people-groups': 'Muro de los pueblos', 'tab.bible-posters': 'Carteles bíblicos', - 'tab.bless-india-posters': 'Bendigan a la India: carteles', + 'tab.bless-india-posters': 'Pósteres «Bendice a la India»', experimentalSub: 'mapa experimental', lab: 'beta', loading: 'Cargando {label}…', loadFailed: 'No se pudo cargar {label}.', manifestHint: 'Esta pestaña se compone a partir de manifest.json: compila el árbol o sirve el árbol compilado para cargarla.', @@ -50,7 +50,7 @@ export const STRINGS = { 'tab.poster-design': 'Conception d’affiches', 'sub.poster-design': 'tous les styles et formats d’affiche', 'tab.wall-of-people-groups': 'Mur des peuples', 'tab.bible-posters': 'Affiches bibliques', - 'tab.bless-india-posters': 'Bénissez l’Inde : affiches', + 'tab.bless-india-posters': 'Affiches « Bénis l’Inde »', experimentalSub: 'carte expérimentale', lab: 'bêta', loading: 'Chargement de {label}…', loadFailed: 'Impossible de charger {label}.', manifestHint: "Cet onglet est composé à partir de manifest.json : construisez l'arborescence ou servez l'arborescence construite pour le charger.", @@ -65,7 +65,7 @@ export const STRINGS = { 'tab.poster-design': 'Postergestaltung', 'sub.poster-design': 'alle Posterstile und -größen', 'tab.wall-of-people-groups': 'Wand der Volksgruppen', 'tab.bible-posters': 'Bibelposter', - 'tab.bless-india-posters': 'Segnet Indien: Poster', + 'tab.bless-india-posters': '„Segne Indien“-Poster', experimentalSub: 'experimentelle Karte', lab: 'Beta', loading: '{label} wird geladen…', loadFailed: '{label} konnte nicht geladen werden.', manifestHint: 'Dieser Tab wird aus manifest.json zusammengesetzt – bauen Sie den Baum oder stellen Sie den gebauten Baum bereit, um ihn zu laden.', @@ -80,7 +80,7 @@ export const STRINGS = { 'tab.poster-design': 'Design de cartazes', 'sub.poster-design': 'todos os estilos e tamanhos de cartaz', 'tab.wall-of-people-groups': 'Mural dos povos', 'tab.bible-posters': 'Cartazes bíblicos', - 'tab.bless-india-posters': 'Abençoem a Índia: cartazes', + 'tab.bless-india-posters': 'Pôsteres «Abençoe a Índia»', experimentalSub: 'mapa experimental', lab: 'beta', loading: 'Carregando {label}…', loadFailed: 'Não foi possível carregar {label}.', manifestHint: 'Esta aba é composta a partir do manifest.json — compile a árvore ou sirva a árvore compilada para carregá-la.', @@ -95,7 +95,7 @@ export const STRINGS = { 'tab.poster-design': 'Design dei poster', 'sub.poster-design': 'tutti gli stili e i formati dei poster', 'tab.wall-of-people-groups': 'Muro dei popoli', 'tab.bible-posters': 'Poster biblici', - 'tab.bless-india-posters': 'Benedite l’India: poster', + 'tab.bless-india-posters': 'Poster «Benedici l’India»', experimentalSub: 'mappa sperimentale', lab: 'beta', loading: 'Caricamento di {label}…', loadFailed: 'Impossibile caricare {label}.', manifestHint: "Questa scheda è composta da manifest.json: compila l'albero o pubblica l'albero compilato per caricarla.", @@ -110,7 +110,7 @@ export const STRINGS = { 'tab.poster-design': 'Design de afișe', 'sub.poster-design': 'toate stilurile și dimensiunile de afiș', 'tab.wall-of-people-groups': 'Zidul popoarelor', 'tab.bible-posters': 'Afișe biblice', - 'tab.bless-india-posters': 'Binecuvântați India: afișe', + 'tab.bless-india-posters': 'Postere „Binecuvântează India”', experimentalSub: 'hartă experimentală', lab: 'beta', loading: 'Se încarcă {label}…', loadFailed: '{label} nu a putut fi încărcat.', manifestHint: 'Această filă este compusă din manifest.json — construiți arborele sau serviți arborele construit pentru a o încărca.', @@ -125,7 +125,7 @@ export const STRINGS = { 'tab.poster-design': 'Дизайн плакатов', 'sub.poster-design': 'все стили и размеры плакатов', 'tab.wall-of-people-groups': 'Стена народов', 'tab.bible-posters': 'Библейские плакаты', - 'tab.bless-india-posters': 'Благословляйте Индию: плакаты', + 'tab.bless-india-posters': 'Плакаты «Благослови Индию»', experimentalSub: 'экспериментальная карта', lab: 'бета', loading: 'Загрузка: {label}…', loadFailed: 'Не удалось загрузить: {label}.', manifestHint: 'Эта вкладка собирается из manifest.json — соберите дерево или разместите собранное дерево, чтобы загрузить её.', @@ -140,7 +140,7 @@ export const STRINGS = { 'tab.poster-design': 'تصميم الملصقات', 'sub.poster-design': 'كل أنماط الملصقات وأحجامها', 'tab.wall-of-people-groups': 'جدار الشعوب', 'tab.bible-posters': 'ملصقات الكتاب المقدس', - 'tab.bless-india-posters': 'باركوا الهند: ملصقات', + 'tab.bless-india-posters': 'ملصقات باركوا الهند', experimentalSub: 'خريطة تجريبية', lab: 'تجريبي', loading: 'جارٍ تحميل {label}…', loadFailed: 'تعذّر تحميل {label}.', manifestHint: 'تُبنى علامة التبويب هذه من manifest.json — ابنِ الشجرة أو قدّم الشجرة المبنية لتحميلها.', @@ -155,7 +155,7 @@ export const STRINGS = { 'tab.poster-design': 'पोस्टर डिज़ाइन', 'sub.poster-design': 'हर पोस्टर शैली और आकार', 'tab.wall-of-people-groups': 'जनसमूहों की दीवार', 'tab.bible-posters': 'बाइबल पोस्टर', - 'tab.bless-india-posters': 'भारत को आशीष दो: पोस्टर', + 'tab.bless-india-posters': 'भारत को आशीष दें — पोस्टर', experimentalSub: 'प्रायोगिक मानचित्र', lab: 'बीटा', loading: '{label} लोड हो रहा है…', loadFailed: '{label} लोड नहीं हो सका।', manifestHint: 'यह टैब manifest.json से बनता है — इसे लोड करने के लिए ट्री बनाएँ या बना हुआ ट्री सर्व करें।', @@ -170,7 +170,7 @@ export const STRINGS = { 'tab.poster-design': '海报设计', 'sub.poster-design': '所有海报样式与尺寸', 'tab.wall-of-people-groups': '民族之墙', 'tab.bible-posters': '圣经海报', - 'tab.bless-india-posters': '祝福印度:海报', + 'tab.bless-india-posters': '祝福印度海报', experimentalSub: '实验性地图', lab: '测试版', loading: '正在加载{label}…', loadFailed: '无法加载{label}。', manifestHint: '此标签页由 manifest.json 组成——请构建目录树或提供已构建的目录树以加载它。',