From 2cea4f84044764c125180a0785a144e8856c8de9 Mon Sep 17 00:00:00 2001 From: Meir Michanie Date: Thu, 15 Oct 2026 22:27:19 +0200 Subject: [PATCH] fix(i18n): Panoramax count line says nearest photo, not its photos Panoramax's coverageLabel action is 'click a line for its nearest photo' (like KartaView's) while it counts sequences, but the count-line discriminator keyed only off the noun, so Panoramax fell through to the default pair and promised 'its photos'. Discriminate on the action first, then the noun, and add the sequences + nearest-photo pair (KartaView keeps streets + nearest-photo; the default keeps sequences + photos). --- src/i18n/locales/es.json | 7 ++++- src/i18n/locales/ru.json | 8 ++++- src/ui/streetLevelPresentation.js | 52 ++++++++++++++++++++----------- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/i18n/locales/es.json b/src/i18n/locales/es.json index d9d0315e2..7d36002ee 100644 --- a/src/i18n/locales/es.json +++ b/src/i18n/locales/es.json @@ -2779,5 +2779,10 @@ "Show the complete infrared image; 0% filter strength": "Muestra la imagen infrarroja completa; intensidad del filtro 0%", "FILTER": "FILTRO", "Cloud filter strength": "Intensidad del filtro de nubes", - "Panoramax answered HTTP {status}": "Panoramax respondió HTTP {status}" + "Panoramax answered HTTP {status}": "Panoramax respondió HTTP {status}", + "{n} sequences in view · click a line for its nearest photo": { + "one": "{n} secuencia a la vista · haz clic en una línea para su foto más cercana", + "many": "{n} secuencias a la vista · haz clic en una línea para su foto más cercana", + "other": "{n} secuencias a la vista · haz clic en una línea para su foto más cercana" + } } diff --git a/src/i18n/locales/ru.json b/src/i18n/locales/ru.json index ab61f56cc..918edac62 100644 --- a/src/i18n/locales/ru.json +++ b/src/i18n/locales/ru.json @@ -2836,5 +2836,11 @@ "Show the complete infrared image; 0% filter strength": "Показать полное ИК-изображение; сила фильтра 0%", "FILTER": "ФИЛЬТР", "Cloud filter strength": "Сила фильтра облаков", - "Panoramax answered HTTP {status}": "Panoramax ответил: HTTP {status}" + "Panoramax answered HTTP {status}": "Panoramax ответил: HTTP {status}", + "{n} sequences in view · click a line for its nearest photo": { + "one": "{n} съёмка в кадре · щёлкните линию, чтобы открыть ближайшую фотографию", + "few": "{n} съёмки в кадре · щёлкните линию, чтобы открыть ближайшую фотографию", + "many": "{n} съёмок в кадре · щёлкните линию, чтобы открыть ближайшую фотографию", + "other": "{n} съёмки в кадре · щёлкните линию, чтобы открыть ближайшую фотографию" + } } diff --git a/src/ui/streetLevelPresentation.js b/src/ui/streetLevelPresentation.js index 579452336..0f468edd6 100644 --- a/src/ui/streetLevelPresentation.js +++ b/src/ui/streetLevelPresentation.js @@ -257,29 +257,45 @@ function presentMeta(state) { ); const hint = translateHint(state.coverage.hint); if (state.coverage.count > 0) { - // A provider whose lines are not sequences carries its wording as data - // (coverageLabel); its count line needs its own tn pair so every language - // gets real plural forms. New wording: add a pair here and to the catalogs. - const count = state.coverage.count; - const countLine = - state.coverage.label?.noun === 'streets' - ? tn( - count, - '{n} street in view · click a line for its nearest photo', - '{n} streets in view · click a line for its nearest photo', - { n: formatNumber(count) }, - ) - : tn( - count, - '{n} sequence in view · click a line for its photos', - '{n} sequences in view · click a line for its photos', - { n: formatNumber(count) }, - ); + const countLine = coverageCountLine(state.coverage); return [countLine, hint].filter(Boolean).join(' · '); } return hint; } +/** + * The coverage count line. Providers carry their wording as data + * (coverageLabel noun/action); each combination needs its own literal tn + * pair so every language gets real plural forms — the noun cannot inflect + * through a placeholder in Russian. New wording: add a pair here and to the + * catalogs (es.json/ru.json). + * @param {{count: number, label?: {noun?: string, action?: string}|null}} coverage + */ +function coverageCountLine(coverage) { + const count = coverage.count; + const values = { n: formatNumber(count) }; + if (coverage.label?.action === 'click a line for its nearest photo') + return coverage.label.noun === 'streets' + ? tn( + count, + '{n} street in view · click a line for its nearest photo', + '{n} streets in view · click a line for its nearest photo', + values, + ) + : tn( + count, + '{n} sequence in view · click a line for its nearest photo', + '{n} sequences in view · click a line for its nearest photo', + values, + ); + return tn( + count, + '{n} sequence in view · click a line for its photos', + '{n} sequences in view · click a line for its photos', + values, + ); +} + /** @param {{now?: number}} [options] Clock for the SINCE readout. */ export function presentStreetLevelPanel(state, { now = Date.now() } = {}) { const enabled = state.enabled === true;