diff --git a/library/i18n/locales/ar/gospel.json b/library/i18n/locales/ar/gospel.json index c57fcebce..bcd4fd776 100644 --- a/library/i18n/locales/ar/gospel.json +++ b/library/i18n/locales/ar/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "لا شيء موجود، ولا أحد يصلّي", "concentrates": "أين تتركّز الفجوة", "linkUnchecked": "لم يتم فحص هذا الرابط." + }, + "rows": { + "scriptureHere": "الكتاب المقدس بهذه اللغة", + "audio": "الكتاب المقدس", + "bibleVideo": "فيديو كتابي", + "gospelPresentation": "عرض الإنجيل", + "studyNotes": "ملاحظات دراسية", + "readOnline": "القراءة عبر الإنترنت", + "audioScripture": "كتاب مقدس مسموع", + "listenBrowser": "استمع في المتصفح", + "inBrowser": "في المتصفح — {media}", + "readHere": "اقرأ بهذه اللغة", + "listenHere": "استمع بهذه اللغة", + "wordsOfLife": "كلمات الحياة — {name}", + "gospelAudio": "تسجيلات الإنجيل", + "discipleship": "تدريب {brand} على صناعة التلاميذ" } } diff --git a/library/i18n/locales/de/gospel.json b/library/i18n/locales/de/gospel.json index 4d23116f4..60308282b 100644 --- a/library/i18n/locales/de/gospel.json +++ b/library/i18n/locales/de/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "Nichts gefunden, und niemand betet", "concentrates": "Wo sich die Lücke ballt", "linkUnchecked": "Dieser Link wurde nicht geprüft." + }, + "rows": { + "scriptureHere": "Bibel in dieser Sprache", + "audio": "Bibel", + "bibleVideo": "Bibelvideo", + "gospelPresentation": "Evangeliumsdarstellung", + "studyNotes": "Studiennotizen", + "readOnline": "online lesen", + "audioScripture": "Bibel als Audio", + "listenBrowser": "Im Browser anhören", + "inBrowser": "Im Browser — {media}", + "readHere": "In dieser Sprache lesen", + "listenHere": "In dieser Sprache hören", + "wordsOfLife": "Worte des Lebens — {name}", + "gospelAudio": "Evangeliums-Audio", + "discipleship": "{brand} Jüngerschafts-Schulung" } } diff --git a/library/i18n/locales/en/gospel.json b/library/i18n/locales/en/gospel.json index cd392ab1e..3b1fe364b 100644 --- a/library/i18n/locales/en/gospel.json +++ b/library/i18n/locales/en/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "Nothing found, and nobody praying", "concentrates": "Where the gap concentrates", "linkUnchecked": "This link has not been checked." + }, + "rows": { + "scriptureHere": "Scripture in this language", + "audio": "Scripture", + "bibleVideo": "Bible video", + "gospelPresentation": "Gospel presentation", + "studyNotes": "study notes", + "readOnline": "read online", + "audioScripture": "Audio Scripture", + "listenBrowser": "Listen in a browser", + "inBrowser": "In a browser — {media}", + "readHere": "Read in this language", + "listenHere": "Listen in this language", + "wordsOfLife": "Words of Life — {name}", + "gospelAudio": "Gospel audio", + "discipleship": "{brand} discipleship training" } } diff --git a/library/i18n/locales/es/gospel.json b/library/i18n/locales/es/gospel.json index 87fe44e26..67b3d37e9 100644 --- a/library/i18n/locales/es/gospel.json +++ b/library/i18n/locales/es/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "Nada encontrado, y nadie orando", "concentrates": "Dónde se concentra la brecha", "linkUnchecked": "Este enlace no ha sido verificado." + }, + "rows": { + "scriptureHere": "Escritura en esta lengua", + "audio": "Escritura", + "bibleVideo": "Video bíblico", + "gospelPresentation": "Presentación del evangelio", + "studyNotes": "notas de estudio", + "readOnline": "leer en línea", + "audioScripture": "Escritura en audio", + "listenBrowser": "Escuchar en el navegador", + "inBrowser": "En el navegador — {media}", + "readHere": "Leer en esta lengua", + "listenHere": "Escuchar en esta lengua", + "wordsOfLife": "Palabras de Vida — {name}", + "gospelAudio": "Audio del evangelio", + "discipleship": "formación de discipulado {brand}" } } diff --git a/library/i18n/locales/fr/gospel.json b/library/i18n/locales/fr/gospel.json index bda7a21c9..20ddcd578 100644 --- a/library/i18n/locales/fr/gospel.json +++ b/library/i18n/locales/fr/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "Rien trouvé, et personne ne prie", "concentrates": "Où l’écart se concentre", "linkUnchecked": "Ce lien n’a pas été vérifié." + }, + "rows": { + "scriptureHere": "Écriture dans cette langue", + "audio": "Écriture", + "bibleVideo": "Vidéo biblique", + "gospelPresentation": "Présentation de l’Évangile", + "studyNotes": "notes d’étude", + "readOnline": "lire en ligne", + "audioScripture": "Écriture audio", + "listenBrowser": "Écouter dans le navigateur", + "inBrowser": "Dans le navigateur — {media}", + "readHere": "Lire dans cette langue", + "listenHere": "Écouter dans cette langue", + "wordsOfLife": "Paroles de Vie — {name}", + "gospelAudio": "Audio de l’Évangile", + "discipleship": "formation au discipulat {brand}" } } diff --git a/library/i18n/locales/hi/gospel.json b/library/i18n/locales/hi/gospel.json index 3fe3b907d..a79c03045 100644 --- a/library/i18n/locales/hi/gospel.json +++ b/library/i18n/locales/hi/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "कुछ नहीं मिला, और कोई प्रार्थना नहीं कर रहा", "concentrates": "अंतर कहाँ केंद्रित है", "linkUnchecked": "यह लिंक जाँचा नहीं गया है।" + }, + "rows": { + "scriptureHere": "इस भाषा में पवित्रशास्त्र", + "audio": "पवित्रशास्त्र", + "bibleVideo": "बाइबल वीडियो", + "gospelPresentation": "सुसमाचार प्रस्तुति", + "studyNotes": "अध्ययन टिप्पणियाँ", + "readOnline": "ऑनलाइन पढ़ें", + "audioScripture": "ऑडियो पवित्रशास्त्र", + "listenBrowser": "ब्राउज़र में सुनें", + "inBrowser": "ब्राउज़र में — {media}", + "readHere": "इस भाषा में पढ़ें", + "listenHere": "इस भाषा में सुनें", + "wordsOfLife": "जीवन के वचन — {name}", + "gospelAudio": "सुसमाचार ऑडियो", + "discipleship": "{brand} शिष्यत्व प्रशिक्षण" } } diff --git a/library/i18n/locales/it/gospel.json b/library/i18n/locales/it/gospel.json index 0373b725a..40c05738b 100644 --- a/library/i18n/locales/it/gospel.json +++ b/library/i18n/locales/it/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "Nulla trovato, e nessuno in preghiera", "concentrates": "Dove si concentra il divario", "linkUnchecked": "Questo collegamento non è stato verificato." + }, + "rows": { + "scriptureHere": "Scrittura in questa lingua", + "audio": "Scrittura", + "bibleVideo": "Video biblico", + "gospelPresentation": "Presentazione del vangelo", + "studyNotes": "note di studio", + "readOnline": "leggi online", + "audioScripture": "Scrittura audio", + "listenBrowser": "Ascolta nel browser", + "inBrowser": "Nel browser — {media}", + "readHere": "Leggi in questa lingua", + "listenHere": "Ascolta in questa lingua", + "wordsOfLife": "Parole di Vita — {name}", + "gospelAudio": "Audio del vangelo", + "discipleship": "formazione al discepolato {brand}" } } diff --git a/library/i18n/locales/pt/gospel.json b/library/i18n/locales/pt/gospel.json index 2f79a6d81..aa464483f 100644 --- a/library/i18n/locales/pt/gospel.json +++ b/library/i18n/locales/pt/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "Nada encontrado, e ninguém orando", "concentrates": "Onde a lacuna se concentra", "linkUnchecked": "Este link não foi verificado." + }, + "rows": { + "scriptureHere": "Escritura nesta língua", + "audio": "Escritura", + "bibleVideo": "Vídeo bíblico", + "gospelPresentation": "Apresentação do evangelho", + "studyNotes": "notas de estudo", + "readOnline": "ler online", + "audioScripture": "Escritura em áudio", + "listenBrowser": "Ouvir no navegador", + "inBrowser": "No navegador — {media}", + "readHere": "Ler nesta língua", + "listenHere": "Ouvir nesta língua", + "wordsOfLife": "Palavras de Vida — {name}", + "gospelAudio": "Áudio do evangelho", + "discipleship": "treinamento de discipulado {brand}" } } diff --git a/library/i18n/locales/ro/gospel.json b/library/i18n/locales/ro/gospel.json index 3541599c1..51f0805ca 100644 --- a/library/i18n/locales/ro/gospel.json +++ b/library/i18n/locales/ro/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "Nimic găsit și nimeni nu se roagă", "concentrates": "Unde se concentrează golul", "linkUnchecked": "Acest link nu a fost verificat." + }, + "rows": { + "scriptureHere": "Scriptura în această limbă", + "audio": "Scriptură", + "bibleVideo": "Video biblic", + "gospelPresentation": "Prezentarea Evangheliei", + "studyNotes": "note de studiu", + "readOnline": "citește online", + "audioScripture": "Scriptură audio", + "listenBrowser": "Ascultă în browser", + "inBrowser": "În browser — {media}", + "readHere": "Citește în această limbă", + "listenHere": "Ascultă în această limbă", + "wordsOfLife": "Cuvintele Vieții — {name}", + "gospelAudio": "Audio al Evangheliei", + "discipleship": "instruire de ucenicizare {brand}" } } diff --git a/library/i18n/locales/ru/gospel.json b/library/i18n/locales/ru/gospel.json index d0303423a..68a762c78 100644 --- a/library/i18n/locales/ru/gospel.json +++ b/library/i18n/locales/ru/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "Ничего не найдено, и никто не молится", "concentrates": "Где сосредоточен разрыв", "linkUnchecked": "Эта ссылка не проверялась." + }, + "rows": { + "scriptureHere": "Писание на этом языке", + "audio": "Писание", + "bibleVideo": "Библейское видео", + "gospelPresentation": "Изложение Евангелия", + "studyNotes": "учебные заметки", + "readOnline": "читать онлайн", + "audioScripture": "Аудио-Писание", + "listenBrowser": "Слушать в браузере", + "inBrowser": "В браузере — {media}", + "readHere": "Читать на этом языке", + "listenHere": "Слушать на этом языке", + "wordsOfLife": "Слова жизни — {name}", + "gospelAudio": "Аудио Евангелия", + "discipleship": "обучение ученичеству {brand}" } } diff --git a/library/i18n/locales/zh/gospel.json b/library/i18n/locales/zh/gospel.json index 4112a416b..ed5faff81 100644 --- a/library/i18n/locales/zh/gospel.json +++ b/library/i18n/locales/zh/gospel.json @@ -420,5 +420,21 @@ "nobodyPraying": "一无所获,也无人祷告", "concentrates": "差距集中在哪里", "linkUnchecked": "此链接尚未核查。" + }, + "rows": { + "scriptureHere": "这种语言的圣经", + "audio": "圣经", + "bibleVideo": "圣经视频", + "gospelPresentation": "福音陈述", + "studyNotes": "研读注释", + "readOnline": "在线阅读", + "audioScripture": "有声圣经", + "listenBrowser": "在浏览器中收听", + "inBrowser": "在浏览器中 — {media}", + "readHere": "用这种语言阅读", + "listenHere": "用这种语言收听", + "wordsOfLife": "生命之道 — {name}", + "gospelAudio": "福音录音", + "discipleship": "{brand} 门徒训练" } } diff --git a/plugin-designs/gospel-resources/gospel-resource-rows.js b/plugin-designs/gospel-resources/gospel-resource-rows.js index 4179f9484..4d181a014 100644 --- a/plugin-designs/gospel-resources/gospel-resource-rows.js +++ b/plugin-designs/gospel-resources/gospel-resource-rows.js @@ -41,21 +41,36 @@ export const hasReadableScripture = (c) => */ /** Scripture Earth directory names, as a reader would say them. */ -const SE_KIND = { PDF: 'PDF', audio: 'audio', sab: 'app', study: 'study notes', viewer: 'read online' } +// The VALUES here are displayed (joined into a row's scope), so they are labels and take keys; the +// KEYS are the upstream feed's own codes and must never be translated. PDF/audio/app stay as they +// are: an abbreviation and two words that are the same token in the locales we ship. +const SE_KIND = (tx) => ({ PDF: 'PDF', audio: 'audio', sab: 'app', + study: tx('gospel.rows.studyNotes', 'study notes'), viewer: tx('gospel.rows.readOnline', 'read online') }) /** * Every resource a language offers, flattened for a list or a table. * @param {object} c one entry of the pin index's codes[] * @returns {{url:string,title:string,type:string,scope:string}[]} */ -export function resourceRows(c) { +// ★ THE FALLBACKS BELOW ARE UI TEXT, NOT DATA. Each `c.x || 'English'` is shown when a record +// carries no name of its own, so an Arabic or Chinese reader saw English for exactly the rows whose +// source was least complete. check:hardcoded-english does not read .js files yet, which is why these +// survived the bundle's sweep. +// +// `t` is PASSED IN rather than imported: this module is a pure function with no component context, +// and the plugin already threads its translator the same way. It is optional and falls back to the +// English written here, so a caller without a translator degrades to today's behaviour. +// +// 'JESUS Film' below is deliberately NOT keyed: it is the project's name, not a label. +export function resourceRows(c, t = null) { + const tx = (key, en) => { try { const v = t && t(key); return v && v !== key ? v : en } catch (_) { return en } } if (!c) return [] const out = [] const add = (title, type, url, scope = '') => { if (url) out.push({ url, title, type, scope }) } - add(c.sv || 'Scripture in this language', 'Scripture', c.s, c.ss || '') + add(c.sv || tx('gospel.rows.scriptureHere', 'Scripture in this language'), 'Scripture', c.s, c.ss || '') /* c.fT is set only where the JESUS Film component does NOT carry this language and a different JESUS Film Project feature does — The Savior, Magdalena. Calling that "JESUS Film" would be the same class of lie as calling Open Bible Stories Scripture. */ @@ -66,26 +81,32 @@ export function resourceRows(c) { if (c.au) { const media = String(c.au.m || 'audio') add( - c.au.n || 'Scripture', + c.au.n || tx('gospel.rows.audio', 'Scripture'), /* ⚠ ONE RECORD, TWO CAPABILITIES, AND THE TYPE ONLY SAID ONE. Faith Comes By Hearing's media list is often "audio, text, video": this typed every such row 'Audio Scripture', so the access table's byType.Scripture never saw it and 2,001 people groups were published as "watch or hear, cannot read" while their own readable text sat behind that link. TEXT decides the type; the media list stays in the scope so nothing is hidden, and the access builder counts a Scripture row whose scope names audio as hearable too. */ - /text/.test(media) ? 'Scripture' : 'Audio Scripture', + /text/.test(media) ? tx('gospel.rows.audio', 'Scripture') : tx('gospel.rows.audioScripture', 'Audio Scripture'), c.au.u, - media === 'audio' ? 'Listen in a browser' : `In a browser — ${media}`, + media === 'audio' ? tx('gospel.rows.listenBrowser', 'Listen in a browser') + : tx('gospel.rows.inBrowser', 'In a browser — {media}').replace('{media}', media), ) } - if (c.bv) add(c.bv.n || 'Bible video', 'Bible video', c.bv.u, c.bv.sc || '') - if (c.gp) add(c.gp.n || 'Gospel presentation', 'Gospel presentation', c.gp.u, 'Read in this language') + if (c.bv) add(c.bv.n || tx('gospel.rows.bibleVideo', 'Bible video'), 'Bible video', c.bv.u, c.bv.sc || '') + if (c.gp) add(c.gp.n || tx('gospel.rows.gospelPresentation', 'Gospel presentation'), 'Gospel presentation', c.gp.u, tx('gospel.rows.readHere', 'Read in this language')) if (c.se) { - add('Scripture Earth', 'Scripture', c.se.u, (c.se.k || []).map((k) => SE_KIND[k] || k).join(', ')) + add('Scripture Earth', 'Scripture', c.se.u, (c.se.k || []).map((k) => SE_KIND(tx)[k] || k).join(', ')) } if (c.ga) { - add(c.ga.n ? `Words of Life — ${c.ga.n}` : 'Gospel audio', 'Gospel audio', c.ga.u, 'Listen in this language') + add(c.ga.n ? tx('gospel.rows.wordsOfLife', 'Words of Life — {name}').replace('{name}', c.ga.n) + : tx('gospel.rows.gospelAudio', 'Gospel audio'), 'Gospel audio', c.ga.u, + tx('gospel.rows.listenHere', 'Listen in this language')) } - add('Zume discipleship training', 'Discipleship training', c.z) + // The brand is INTERPOLATED, not retyped by a translator: "Zume" is the publisher's name and must + // survive every locale unchanged, while "discipleship training" is an ordinary noun phrase. + add(tx('gospel.rows.discipleship', '{brand} discipleship training').replace('{brand}', 'Zume'), + 'Discipleship training', c.z) return out } diff --git a/plugin-designs/gospel-resources/resources-list.vue b/plugin-designs/gospel-resources/resources-list.vue index 1b1883986..c4a32587f 100644 --- a/plugin-designs/gospel-resources/resources-list.vue +++ b/plugin-designs/gospel-resources/resources-list.vue @@ -105,7 +105,7 @@ const languages = computed(() => { // listed only c.s and c.d, so film, audio, Bible video, tracts, Scripture Earth and // GRN never appeared here — a language whose only resource was a Words of Life // recording rendered with no links while the map offered a working one. - const res = resourceRows(c) + const res = resourceRows(c, tr) e = { iso: code, language: c.l || 'unknown',