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;