From 7d76950d555ef156763c7681a60c76e769310446 Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Sat, 25 Jan 2020 16:25:04 +0000 Subject: [PATCH] Use Osmose translation strings for issue titles This is just step one in the process while we wait for the API to supply further strings and filtering to reduce the amount of string data requested (since we don't need it all). Strings are requested when the layer is first enabled and cached for the current language (plus English as a backup). --- data/core.yaml | 42 --------------------- data/qa_errors.json | 50 ++++++++++++------------- dist/locales/en.json | 47 ----------------------- modules/services/osmose.js | 75 ++++++++++++++++++++++++++++++++++--- modules/svg/osmose.js | 3 +- modules/ui/osmose_header.js | 17 +++------ 6 files changed, 103 insertions(+), 131 deletions(-) diff --git a/data/core.yaml b/data/core.yaml index 67a7f6912..df409495b 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -831,58 +831,35 @@ en: title: Osmose Issue error_types: 0: - title: 'Building Intersection' description: '{0} and {1} intersect.' 0-3: - title: 'Suspiciously Small Building' description: '{0} is a suspisciously small building.' 0-4: - title: 'Gap Between Buildings' description: 'A gap exists between {0} and {1} which looks suspiciously small.' 1040-1: - title: 'Invalid Polygon' description: '{0} intersects itself.' 1050-1: - title: 'Reversed Roundabout' description: '{0} looks like a roundabout mapped in the wrong direction for this location.' 1050-1050: - title: 'Reversed Mini-Roundabout' description: '{0} looks like a mini-roundabout with the incorrect "direction" tag for this location.' 1070: - title: 'Highway intersecting water' description: '{1} intersects with {0}, but there is no junction node, bridge, or tunnel.' - 1070-1: - title: 'Highway intersecting building' - 1070-8: - title: 'Highway intersecting highway' - 1070-10: - title: 'Waterway intersecting waterway' 1150: - title: 'Overlapping Similar Areas' description: '{0} and {1} overlap.' 1190: - title: 'Approximate Way' description: '{0} looks like it could be mapped more accurately.' 1280-1: - title: 'Incorrect Speed Camera' description: '{0} should be on the highway or part of an "enforcement" relation.' 2110-21101: - title: 'Unknown Named Object' description: '{0} has a name but no feature tag.' 2110-21102: - title: 'Missing Relation Type' description: '{0} is missing a "type" tag.' 3040-3040: - title: 'Unusual Tagging' description: '{0} has a non-conventional tag value: "{1}".' 3090-3090: - title: 'Invalid Date' description: '{0} is tagged with an invalid date value: "{1}".' 3161: - title: 'Missing Parking Access' description: 'There is no highway leading to {0}.' - 3200: - title: 'Invalid Area Tagging' 3200-32001: description: '{0} is tagged "area=yes", but this feature is an area by default.' 3200-32002: @@ -890,52 +867,36 @@ en: 3200-32003: description: '{0} is tagged "area=no", but this feature already isn''t an area.' 3220: - title: 'All Access Allowed' description: '{0} has an "access=yes" or "access=permissive" tag which permits use by all transport modes (ski, horse, hazmat, etc.).' 3250-32501: - title: 'Invalid Opening Hours' description: '{0} has an invalid value for the "opening_hours" tag.' 4010: - title: 'Deprecated Tagging' description: '{0} uses tag "{1}" which is deprecated in favour of "{2}".' 4030-900: - title: 'Conflicting Tags' description: '{0} is tagged with both "{1}" and "{2}".' 4080: - title: 'Object Mapped Twice' description: '{0} and {1} both appear to represent the same object.' - 5010: - title: 'Orthographic Error' 5010-803: description: 'The "name" of {0} is written in all capitals.' 5010-903: description: 'The "name" of {0} has excessive space characters.' 5070-50703: - title: 'Unexpected Symbol' description: '{0} has an unexpected symbol, {2}, in the "{1}" tag.' 5070-50704: - title: 'Unbalanced Punctuation' description: '{0} has an unbalanced {1} character in its name.' 5070-50705: - title: 'Unexpected Punctuation' description: '{0} has an unexpected {1} character in its name.' 7040: - title: 'Unfinished Power Line' description: 'A power line appears to be unfinished at {0}.' 7040-1: - title: 'Lone Power Support' description: '{0} is a power tower or pole with no connected power lines.' 7040-4: - title: 'Extra Power Line Node' description: 'Power lines should only have nodes at supports and {0} is not tagged as a pole or tower.' 7090-1: - title: 'Disconnected Level Crossing' description: '{0} is a level crossing at a non-junction node.' 7090-3: - title: 'Disconnected Highway Feature' description: '{0} is highway feature or barrier with no connected highway.' 8300: - title: 'Traffic Sign Suggestion' description: 'Traffic signs detected by Mapillary suggest there may be an unmapped {0} nearby.' parts: 1: 'speed limit' @@ -945,7 +906,6 @@ en: 34: 'set of speed bumps' 39: 'living street' 8360: - title: 'Missing Street Object' description: 'Object detection by Mapillary suggests there may be an unmapped {0} nearby.' parts: 1: 'bench' @@ -954,10 +914,8 @@ en: 4: 'fire hydrant' 5: 'set of traffic signals' 9010-9010001: - title: 'Unnecessary Tag' description: '{0} is redundantly tagged with "{1}".' 9010-9010003: - title: 'Descriptive Name' description: '{0} appears to have a descriptive name: "{1}".' improveOSM: title: ImproveOSM Detection diff --git a/data/qa_errors.json b/data/qa_errors.json index b41bbfe6c..613c6cb5c 100644 --- a/data/qa_errors.json +++ b/data/qa_errors.json @@ -12,31 +12,31 @@ }, "osmose": { "items": [ - "0", - "1040", - "1050", - "1070", - "1150", - "1190", - "1280", - "2110", - "3040", - "3090", - "3161", - "3200", - "3220", - "3250", - "4010", - "4030", - "4080", - "5010", - "7040", - "7090", - "5010", - "5070", - "8300", - "8360", - "9010" + 0, + 1040, + 1050, + 1070, + 1150, + 1190, + 1280, + 2110, + 3040, + 3090, + 3161, + 3200, + 3220, + 3250, + 4010, + 4030, + 4080, + 5010, + 7040, + 7090, + 5010, + 5070, + 8300, + 8360, + 9010 ], "errorIcons": { "0-1": "maki-home", diff --git a/dist/locales/en.json b/dist/locales/en.json index 1d212bee1..98dda7275 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -1035,49 +1035,33 @@ "title": "Osmose Issue", "error_types": { "0": { - "title": "Building Intersection", "description": "{0} and {1} intersect." }, "1070": { - "title": "Highway intersecting water", "description": "{1} intersects with {0}, but there is no junction node, bridge, or tunnel." }, "1150": { - "title": "Overlapping Similar Areas", "description": "{0} and {1} overlap." }, "1190": { - "title": "Approximate Way", "description": "{0} looks like it could be mapped more accurately." }, "3161": { - "title": "Missing Parking Access", "description": "There is no highway leading to {0}." }, - "3200": { - "title": "Invalid Area Tagging" - }, "3220": { - "title": "All Access Allowed", "description": "{0} has an \"access=yes\" or \"access=permissive\" tag which permits use by all transport modes (ski, horse, hazmat, etc.)." }, "4010": { - "title": "Deprecated Tagging", "description": "{0} uses tag \"{1}\" which is deprecated in favour of \"{2}\"." }, "4080": { - "title": "Object Mapped Twice", "description": "{0} and {1} both appear to represent the same object." }, - "5010": { - "title": "Orthographic Error" - }, "7040": { - "title": "Unfinished Power Line", "description": "A power line appears to be unfinished at {0}." }, "8300": { - "title": "Traffic Sign Suggestion", "description": "Traffic signs detected by Mapillary suggest there may be an unmapped {0} nearby.", "parts": { "1": "speed limit", @@ -1089,7 +1073,6 @@ } }, "8360": { - "title": "Missing Street Object", "description": "Object detection by Mapillary suggests there may be an unmapped {0} nearby.", "parts": { "1": "bench", @@ -1100,52 +1083,33 @@ } }, "0-3": { - "title": "Suspiciously Small Building", "description": "{0} is a suspisciously small building." }, "0-4": { - "title": "Gap Between Buildings", "description": "A gap exists between {0} and {1} which looks suspiciously small." }, "1040-1": { - "title": "Invalid Polygon", "description": "{0} intersects itself." }, "1050-1": { - "title": "Reversed Roundabout", "description": "{0} looks like a roundabout mapped in the wrong direction for this location." }, "1050-1050": { - "title": "Reversed Mini-Roundabout", "description": "{0} looks like a mini-roundabout with the incorrect \"direction\" tag for this location." }, - "1070-1": { - "title": "Highway intersecting building" - }, - "1070-8": { - "title": "Highway intersecting highway" - }, - "1070-10": { - "title": "Waterway intersecting waterway" - }, "1280-1": { - "title": "Incorrect Speed Camera", "description": "{0} should be on the highway or part of an \"enforcement\" relation." }, "2110-21101": { - "title": "Unknown Named Object", "description": "{0} has a name but no feature tag." }, "2110-21102": { - "title": "Missing Relation Type", "description": "{0} is missing a \"type\" tag." }, "3040-3040": { - "title": "Unusual Tagging", "description": "{0} has a non-conventional tag value: \"{1}\"." }, "3090-3090": { - "title": "Invalid Date", "description": "{0} is tagged with an invalid date value: \"{1}\"." }, "3200-32001": { @@ -1158,11 +1122,9 @@ "description": "{0} is tagged \"area=no\", but this feature already isn't an area." }, "3250-32501": { - "title": "Invalid Opening Hours", "description": "{0} has an invalid value for the \"opening_hours\" tag." }, "4030-900": { - "title": "Conflicting Tags", "description": "{0} is tagged with both \"{1}\" and \"{2}\"." }, "5010-803": { @@ -1172,39 +1134,30 @@ "description": "The \"name\" of {0} has excessive space characters." }, "5070-50703": { - "title": "Unexpected Symbol", "description": "{0} has an unexpected symbol, {2}, in the \"{1}\" tag." }, "5070-50704": { - "title": "Unbalanced Punctuation", "description": "{0} has an unbalanced {1} character in its name." }, "5070-50705": { - "title": "Unexpected Punctuation", "description": "{0} has an unexpected {1} character in its name." }, "7040-1": { - "title": "Lone Power Support", "description": "{0} is a power tower or pole with no connected power lines." }, "7040-4": { - "title": "Extra Power Line Node", "description": "Power lines should only have nodes at supports and {0} is not tagged as a pole or tower." }, "7090-1": { - "title": "Disconnected Level Crossing", "description": "{0} is a level crossing at a non-junction node." }, "7090-3": { - "title": "Disconnected Highway Feature", "description": "{0} is highway feature or barrier with no connected highway." }, "9010-9010001": { - "title": "Unnecessary Tag", "description": "{0} is redundantly tagged with \"{1}\"." }, "9010-9010003": { - "title": "Descriptive Name", "description": "{0} appears to have a descriptive name: \"{1}\"." } } diff --git a/modules/services/osmose.js b/modules/services/osmose.js index bc86e74e8..abc9ed70c 100644 --- a/modules/services/osmose.js +++ b/modules/services/osmose.js @@ -3,16 +3,17 @@ import RBush from 'rbush'; import { dispatch as d3_dispatch } from 'd3-dispatch'; import { json as d3_json } from 'd3-fetch'; -import { t } from '../util/locale'; +import { currentLocale, t } from '../util/locale'; import { geoExtent, geoVecAdd } from '../geo'; import { qaError } from '../osm'; import { utilRebind, utilTiler, utilQsString } from '../util'; -import { services } from '../../data/qa_errors.json'; +import { services as qaServices } from '../../data/qa_errors.json'; const tiler = utilTiler(); const dispatch = d3_dispatch('loaded'); const _osmoseUrlRoot = 'https://osmose.openstreetmap.fr/en/api/0.3beta/'; const _erZoom = 14; +const _stringCache = {}; // This gets reassigned if reset let _erCache; @@ -91,7 +92,7 @@ export default { let params = { // Tiles return a maximum # of errors // So we want to filter our request for only types iD supports - item: services.osmose.items.join() + item: qaServices.osmose.items.join() }; // determine the needed tiles to cover the view @@ -121,10 +122,10 @@ export default { data.features.forEach(issue => { const { item, class: error_class, uuid: identifier } = issue.properties; // Item is the type of error, w/ class tells us the sub-type - const error_type = [item, error_class].join('-'); + const error_type = `${item}-${error_class}`; // Filter out unsupported error types (some are too specific or advanced) - if (error_type in services.osmose.errorIcons) { + if (error_type in qaServices.osmose.errorIcons) { let loc = issue.geometry.coordinates; // lon, lat loc = preventCoincident(loc); @@ -225,6 +226,70 @@ export default { }); }, + loadStrings(callback, locale=currentLocale) { + if (locale in _stringCache) { + if (callback) callback(null, _stringCache[locale]); + return; + } + + const langs = { [locale]: true }; + + // Need English strings if not already fetched for fallback values + if (locale != 'en' && !('en' in _stringCache)) { + langs.en = true; + } + + // TODO: Currently all locales are served, in future a param will be available to request specifics + const url = _osmoseUrlRoot + 'items'; + + d3_json(url) + .then(data => { + for (let l in langs) { + _stringCache[l] = {}; + } + + for (let i = 0; i < data.categories.length; i++) { + let cat = data.categories[i]; + + for (let j = 0; j < cat.items.length; j++) { + let item = cat.items[j]; + + // Only need to cache strings for supported error types + // TODO: may be possible to request additional filter by `item` + if (qaServices.osmose.items.indexOf(item.item) !== -1) { + for (let k = 0; k < item.class.length; k++) { + let { class: cl, item: cat } = item.class[k]; + let issueType = `${cat}-${cl}`; + + for (let l in langs) { + _stringCache[l][issueType] = {}; + + let issueStrings = _stringCache[l][issueType]; + + // TODO: Only title is currently served, in future description and other strings will be too + let { title: {[l]: title} } = item.class[k]; + if (title) issueStrings.title = title; + } + } + } + } + } + + if (callback) callback(null, _stringCache[locale]); + }) + .catch(err => { + if (callback) callback(err.message); + }); + }, + + getStrings(issueType, locale=currentLocale) { + const l = (locale in _stringCache) ? _stringCache[locale][issueType] : {}; + const en = ('en' in _stringCache) ? _stringCache['en'][issueType] : {}; + + // Fallback to English if string is untranslated + return Object.assign({}, en, l); + }, + postUpdate(d, callback) { if (_erCache.inflightPost[d.id]) { return callback({ message: 'Error update already inflight', status: -2 }, d); diff --git a/modules/svg/osmose.js b/modules/svg/osmose.js index 77d54e921..70b3c1aa1 100644 --- a/modules/svg/osmose.js +++ b/modules/svg/osmose.js @@ -63,7 +63,8 @@ export function svgOsmose(projection, context, dispatch) { // Enable the layer. This shows the errors and transitions them to visible. function layerOn() { - editOn(); + // Strings supplied by Osmose fetched before showing layer for first time + getService().loadStrings(editOn); drawLayer .style('opacity', 0) diff --git a/modules/ui/osmose_header.js b/modules/ui/osmose_header.js index c2f0ce1aa..36ce763b9 100644 --- a/modules/ui/osmose_header.js +++ b/modules/ui/osmose_header.js @@ -1,5 +1,5 @@ -import { dataEn } from '../../data'; -import { t } from '../util/locale'; +import { services } from '../services'; +import { currentLocale, t } from '../util/locale'; export function uiOsmoseHeader() { @@ -11,15 +11,10 @@ export function uiOsmoseHeader() { if (!d) return unknown; - // Some errors fall back to their category for strings - var i, et; - var keys = [d.error_type, d.item]; - for (i = 0; i < 2; i++) { - et = dataEn.QA.osmose.error_types[keys[i]]; - - if (et && et.title) { - return t('QA.osmose.error_types.' + keys[i] + '.title'); - } + // Issue titles supplied by Osmose + var s = services.osmose.getStrings(d.error_type); + if ('title' in s) { + return s.title; } return unknown;