From d0343c9fa7832f6bf18ac1433a49073d3e4db6c6 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 3 Jan 2019 18:16:28 -0500 Subject: [PATCH] Reintroduce some error localization, fix some nagging parse issues --- data/core.yaml | 64 ++++++++++++++++++-------- data/keepRight.json | 16 +++---- dist/locales/en.json | 66 ++++++++++++++++++--------- modules/services/keepRight.js | 84 +++++++++++++++++++++++++++-------- 4 files changed, 164 insertions(+), 66 deletions(-) diff --git a/data/core.yaml b/data/core.yaml index 03e6c35bc..ebec1d8f9 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -659,19 +659,44 @@ en: save_comment: Save Comment close_comment: Close and Comment ignore_comment: Ignore and Comment - entities: - node: "Node {id}" - way: "Way {id}" - relation: "Relation {id}" + error_parts: + node: node + way: way + relation: relation + highway: highway + railway: railway + waterway: waterway + cycleway: cycleway + cycleway_footpath: 'cycleway/footpath' + riverbank: riverbank + bridge: bridge + tunnel: tunnel + place_of_worship: 'place of worship' + pub: pub + restaurant: restaurant + school: school + university: university + hospital: hospital + library: library + theatre: theatre + courthouse: courthouse + bank: bank + cinema: cinema + pharmacy: pharmacy + cafe: cafe + fast_food: 'fast food' + fuel: fuel + from: from + to: to errorTypes: 20: title: 'Multiple nodes on the same spot' description: 'There is more than one node in this spot. Node IDs: {var1}.' 30: - title: 'Non-closed areas' + title: 'Non-closed area' description: 'This way is tagged with "{var1}" and should be a closed loop.' 40: - title: 'Impossible oneways' + title: 'Impossible oneway' description: 'The first node {var1} of this oneway is not connected to any other way.' 41: description: 'The last node {var1} of this oneway is not connected to any other way.' @@ -680,13 +705,13 @@ en: 43: description: 'You cannot escape from this node because all ways leading to it are oneway.' 50: - title: 'Almost junctions' + title: 'Almost junction' description: 'This node is very close but not connected to way {var1}.' 60: - title: 'Deprecated tags' + title: 'Deprecated tag' description: 'This {var1} uses deprecated tag "{var2}". Please use "{var3}" instead.' 70: - title: 'Missing tags' + title: 'Missing tag' description: 'This {var1} has an empty tag: "{var2}".' 71: description: 'This way has no tags.' @@ -720,19 +745,19 @@ en: title: 'Railway layer conflict' description: 'There are ways in different layers (e.g. tunnel or bridge) meeting at this railway crossing.' 170: - title: 'FIXME tagged items' + title: 'FIXME tagged item' description: '{var1}' 180: title: 'Relation without type' description: 'This relation is missing a "type" tag.' 190: - title: 'Intersection without junctions' + title: 'Intersection without junction' description: 'This {var1} intersects the {var2} {var3} but there is no junction node, bridge, or tunnel.' 200: title: 'Overlapping ways' description: 'This {var1} overlaps the {var2} {var3}.' 210: - title: 'Self-intersecting ways' + title: 'Self-intersecting way' description: 'There is an unspecified issue with self intersecting ways.' 211: description: 'This way contains more than one node multiple times. Nodes are {var1}. This may or may not be an error.' @@ -742,7 +767,7 @@ en: title: 'Misspelled tag' description: 'This {var1} is tagged "{var2}" where "{var3}" looks like "{var4}".' 221: - description: 'This {var1} has a tag with key "{var2}".' + description: 'This {var1} has a suspicious tag "{var2}".' 230: title: 'Layer conflict' description: 'This node is a junction of ways on different layers.' @@ -816,19 +841,20 @@ en: description: 'This roundabout has only {var1} other road(s) connected. Roundabouts typically have 3 or more.' 320: title: 'Improper link connection' - description: 'This way is tagged as "highway={var1}_link" but doesn''t have a connection to any other "{var2}" or "{var3}_link".' + description: 'This way is tagged as "{var1}" but doesn''t have a connection to any other "{var2}" or "{var3}".' 350: - title: 'Improper bridge tags' + title: 'Improper bridge tag' description: 'This bridge doesn''t have a tag in common with its surrounding ways that shows the purpose of this bridge. There should be one of these tags: {var1}.' 360: - title: 'Language unknown' - description: 'It would be nice if this {var1} had an additional tag "name:XX"="{var2}" where XX shows the language of its name "{var2}".' + title: 'Missing local name tag' + description: 'It would be nice if this {var1} had a local name tag "name:XX={var2}" where XX shows the language of its common name "{var2}".' 370: title: 'Doubled places' description: 'This node has tags in common with the surrounding way {var1} {var2} and seems to be redundant.' + including_the_name: "(including the name {name})" 380: title: 'Non-physical use of sport tag' - description: 'This way is tagged "sport={var1}" but has no physical tag (e.g. "leisure", "building", "amenity", or "highway".' + description: 'This way is tagged "{var1}" but has no physical tag (e.g. "leisure", "building", "amenity", or "highway".' 390: title: 'Missing tracktype' description: This track doesn't have a "tracktype" tag. @@ -839,7 +865,7 @@ en: title: 'Missing turn restriction' description: 'Ways {var1} and {var2} join in a very sharp angle here and there is no oneway tag or turn restriction that prevents turning.' 402: - title: 'Impossible angles' + title: 'Impossible angle' description: 'This way bends in a very sharp angle here.' 410: title: 'Website issue' diff --git a/data/keepRight.json b/data/keepRight.json index 0f9cdec9a..e9a168260 100644 --- a/data/keepRight.json +++ b/data/keepRight.json @@ -169,7 +169,7 @@ "title": "", "severity": "error", "description": "The key of this $1's tag is 'key': $2", - "regex": "this (node|way|relation)''s tag is ''key'': key=(.+)" + "regex": "this (node|way|relation)\\'s tag is \\'key\\': (.+)" }, "230": { "title": "layer conflicts", @@ -214,13 +214,13 @@ "title": "no closed loop", "severity": "error", "description": "The boundary of $1 is not closed-loop", - "regex": "boundary of (.+)" + "regex": "boundary of (.+) is" }, "284": { "title": "splitting boundary", "severity": "error", "description": "The boundary of $1 splits here", - "regex": "boundary of (.+)" + "regex": "boundary of (.+) splits" }, "285": { "title": "admin_level too high", @@ -262,7 +262,7 @@ "title": "via is not on the way ends", "severity": "error", "description": "via (node #$1) is not the first or the last member of (from|to) (way #$3)", - "IDs": ["n","w"], + "IDs": ["n", "", "w"], "regex": "via \\(node #(\\d+)\\) is not the first or the last member of (from|to) \\(way #(\\d+)\\)" }, "296": { @@ -316,7 +316,7 @@ "title": "*_link connections", "severity": "error", "description": "This way is tagged as highway=$1_link but doesn't have a connection to any other $1 or $1_link", - "regex": "highway=(\\w+)_link" + "regex": "(highway=.+) but doesn't have a connection to any other (.+) or (.+)" }, "350": { "title": "bridge-tags", @@ -335,14 +335,14 @@ "title": "doubled places", "severity": "error", "description": "This node has tags in common with the surrounding way #$1 ((?:\\(including the name '.+'\\) )?)and seems to be redundand", - "IDs": ["w"], + "IDs": ["w","370"], "regex": "way #(\\d+) ((?:\\(including the name '.+'\\) )?)and" }, "380": { "title": "non-physical use of sport-tag", "severity": "error", "description": "This way is tagged sport=$1 but has no physical tag like e.g. leisure, building, amenity or highway", - "regex": "sport=(\\w+) but" + "regex": "(sport=.+) but" }, "390": { "title": "missing tracktype", @@ -381,7 +381,7 @@ "title": "domain hijacking", "severity": "error", "description": "Possible domain squatting: $1. Suspicious text is: \"$2\"", - "regex": "Possible domain squatting: \\1\\. Suspicious text is: ''(.+)''" + "regex": "Possible domain squatting: \\1\\. Suspicious text is: "(.+)"" }, "413": { "title": "non-match", diff --git a/dist/locales/en.json b/dist/locales/en.json index 724bb79bf..e4b68378b 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -799,10 +799,35 @@ "save_comment": "Save Comment", "close_comment": "Close and Comment", "ignore_comment": "Ignore and Comment", - "entities": { - "node": "Node {id}", - "way": "Way {id}", - "relation": "Relation {id}" + "error_parts": { + "node": "node", + "way": "way", + "relation": "relation", + "highway": "highway", + "railway": "railway", + "waterway": "waterway", + "cycleway": "cycleway", + "cycleway_footpath": "cycleway/footpath", + "riverbank": "riverbank", + "bridge": "bridge", + "tunnel": "tunnel", + "place_of_worship": "place of worship", + "pub": "pub", + "restaurant": "restaurant", + "school": "school", + "university": "university", + "hospital": "hospital", + "library": "library", + "theatre": "theatre", + "courthouse": "courthouse", + "bank": "bank", + "cinema": "cinema", + "pharmacy": "pharmacy", + "cafe": "cafe", + "fast_food": "fast food", + "fuel": "fuel", + "from": "from", + "to": "to" }, "errorTypes": { "20": { @@ -810,11 +835,11 @@ "description": "There is more than one node in this spot. Node IDs: {var1}." }, "30": { - "title": "Non-closed areas", + "title": "Non-closed area", "description": "This way is tagged with \"{var1}\" and should be a closed loop." }, "40": { - "title": "Impossible oneways", + "title": "Impossible oneway", "description": "The first node {var1} of this oneway is not connected to any other way." }, "41": { @@ -827,15 +852,15 @@ "description": "You cannot escape from this node because all ways leading to it are oneway." }, "50": { - "title": "Almost junctions", + "title": "Almost junction", "description": "This node is very close but not connected to way {var1}." }, "60": { - "title": "Deprecated tags", + "title": "Deprecated tag", "description": "This {var1} uses deprecated tag \"{var2}\". Please use \"{var3}\" instead." }, "70": { - "title": "Missing tags", + "title": "Missing tag", "description": "This {var1} has an empty tag: \"{var2}\"." }, "71": { @@ -882,7 +907,7 @@ "description": "There are ways in different layers (e.g. tunnel or bridge) meeting at this railway crossing." }, "170": { - "title": "FIXME tagged items", + "title": "FIXME tagged item", "description": "{var1}" }, "180": { @@ -890,7 +915,7 @@ "description": "This relation is missing a \"type\" tag." }, "190": { - "title": "Intersection without junctions", + "title": "Intersection without junction", "description": "This {var1} intersects the {var2} {var3} but there is no junction node, bridge, or tunnel." }, "200": { @@ -898,7 +923,7 @@ "description": "This {var1} overlaps the {var2} {var3}." }, "210": { - "title": "Self-intersecting ways", + "title": "Self-intersecting way", "description": "There is an unspecified issue with self intersecting ways." }, "211": { @@ -912,7 +937,7 @@ "description": "This {var1} is tagged \"{var2}\" where \"{var3}\" looks like \"{var4}\"." }, "221": { - "description": "This {var1} has a tag with key \"{var2}\"." + "description": "This {var1} has a suspicious tag \"{var2}\"." }, "230": { "title": "Layer conflict", @@ -1011,23 +1036,24 @@ }, "320": { "title": "Improper link connection", - "description": "This way is tagged as \"highway={var1}_link\" but doesn't have a connection to any other \"{var2}\" or \"{var3}_link\"." + "description": "This way is tagged as \"{var1}\" but doesn't have a connection to any other \"{var2}\" or \"{var3}\"." }, "350": { - "title": "Improper bridge tags", + "title": "Improper bridge tag", "description": "This bridge doesn't have a tag in common with its surrounding ways that shows the purpose of this bridge. There should be one of these tags: {var1}." }, "360": { - "title": "Language unknown", - "description": "It would be nice if this {var1} had an additional tag \"name:XX\"=\"{var2}\" where XX shows the language of its name \"{var2}\"." + "title": "Missing local name tag", + "description": "It would be nice if this {var1} had a local name tag \"name:XX={var2}\" where XX shows the language of its common name \"{var2}\"." }, "370": { "title": "Doubled places", - "description": "This node has tags in common with the surrounding way {var1} {var2} and seems to be redundant." + "description": "This node has tags in common with the surrounding way {var1} {var2} and seems to be redundant.", + "including_the_name": "(including the name {name})" }, "380": { "title": "Non-physical use of sport tag", - "description": "This way is tagged \"sport={var1}\" but has no physical tag (e.g. \"leisure\", \"building\", \"amenity\", or \"highway\"." + "description": "This way is tagged \"{var1}\" but has no physical tag (e.g. \"leisure\", \"building\", \"amenity\", or \"highway\"." }, "390": { "title": "Missing tracktype", @@ -1042,7 +1068,7 @@ "description": "Ways {var1} and {var2} join in a very sharp angle here and there is no oneway tag or turn restriction that prevents turning." }, "402": { - "title": "Impossible angles", + "title": "Impossible angle", "description": "This way bends in a very sharp angle here." }, "410": { diff --git a/modules/services/keepRight.js b/modules/services/keepRight.js index 23d7d47c6..a1be47f5d 100644 --- a/modules/services/keepRight.js +++ b/modules/services/keepRight.js @@ -21,7 +21,39 @@ var dispatch = d3_dispatch('loaded'); var _krCache; var _krZoom = 14; -var apibase = 'https://www.keepright.at/'; +var _krUrlRoot = 'https://www.keepright.at/'; +var _krLocalize = { + node: 'node', + way: 'way', + relation: 'relation', + highway: 'highway', + railway: 'railway', + waterway: 'waterway', + cycleway: 'cycleway', + footpath: 'footpath', + 'cycleway/footpath': 'cycleway_footpath', + riverbank: 'riverbank', + bridge: 'bridge', + tunnel: 'tunnel', + place_of_worship: 'place_of_worship', + pub: 'pub', + restaurant: 'restaurant', + school: 'school', + university: 'university', + hospital: 'hospital', + library: 'library', + theatre: 'theatre', + courthouse: 'courthouse', + bank: 'bank', + cinema: 'cinema', + pharmacy: 'pharmacy', + cafe: 'cafe', + fast_food: 'fast_food', + fuel: 'fuel', + from: 'from', + to: 'to' +}; + var defaultRuleset = [ // no 20 - multiple node on same spot - these are mostly boundaries overlapping roads 30, 40, 50, 60, 70, 90, 100, 110, 120, 130, 150, 160, 170, 180, @@ -72,13 +104,13 @@ function updateRtree(item, replace) { function tokenReplacements(d) { if (!(d instanceof krError)) return; + var htmlRegex = new RegExp(/<\/[a-z][\s\S]*>/); var replacements = {}; - var html_re = new RegExp(/<\/[a-z][\s\S]*>/); var errorTemplate = errorTypes[d.which_type]; if (!errorTemplate) { /* eslint-disable no-console */ - console.log('No Template: ', d.error_type); + console.log('No Template: ', d.which_type); console.log(' ', d.description); /* eslint-enable no-console */ return; @@ -92,7 +124,7 @@ function tokenReplacements(d) { var errorMatch = errorRegex.exec(d.description); if (!errorMatch) { /* eslint-disable no-console */ - console.log('Unmatched: ', d.error_type); + console.log('Unmatched: ', d.which_type); console.log(' ', d.description); console.log(' ', errorRegex); /* eslint-enable no-console */ @@ -103,13 +135,13 @@ function tokenReplacements(d) { var group = errorMatch[i]; var idType; - // link IDs if present in the group idType = 'IDs' in errorTemplate ? errorTemplate.IDs[i-1] : ''; - if (idType && group) { + if (idType && group) { // link IDs if present in the group group = parseError(group, idType); - } else if (html_re.test(group)) { - // escape any html in non-IDs + } else if (htmlRegex.test(group)) { // escape any html in non-IDs group = '\\' + group + '\\'; + } else if (_krLocalize[group]) { // some replacement strings can be localized + group = t('QA.keepRight.error_parts.' + _krLocalize[group]); } replacements['var' + i] = group; @@ -126,9 +158,9 @@ function parseError(group, idType) { } // arbitrary node list of form: #ID, #ID, #ID... - function parseError211(list) { + function parseError211(capture) { var newList = []; - var items = list.split(', '); + var items = capture.split(', '); items.forEach(function(item) { // ID has # at the front @@ -140,10 +172,10 @@ function parseError(group, idType) { } // arbitrary way list of form: #ID(layer),#ID(layer),#ID(layer)... - function parseError231(list) { + function parseError231(capture) { var newList = []; // unfortunately 'layer' can itself contain commas, so we split on '),' - var items = list.split('),'); + var items = capture.split('),'); items.forEach(function(item) { var match = item.match(/\#(\d+)\((.+)\)?/); @@ -158,9 +190,9 @@ function parseError(group, idType) { } // arbitrary node/relation list of form: from node #ID,to relation #ID,to node #ID... - function parseError294(list) { + function parseError294(capture) { var newList = []; - var items = list.split(','); + var items = capture.split(','); items.forEach(function(item) { var role; @@ -187,10 +219,21 @@ function parseError(group, idType) { return newList.join(', '); } + // may or may not include the string "(including the name 'name')" + function parseError370(capture) { + if (!capture) return ''; + + var match = capture.match(/\(including the name (\'.+\')\)/); + if (match !== null && match.length) { + return t('QA.keepRight.errorTypes.370.including_the_name', { name: match[1] }); + } + return ''; + } + // arbitrary node list of form: #ID,#ID,#ID... - function parseWarning20(list) { + function parseWarning20(capture) { var newList = []; - var items = list.split(','); + var items = capture.split(','); items.forEach(function(item) { // ID has # at the front @@ -218,6 +261,9 @@ function parseError(group, idType) { case '294': group = parseError294(group); break; + case '370': + group = parseError370(group); + break; case '20': group = parseWarning20(group); } @@ -262,7 +308,7 @@ export default { var rect = tile.extent.rectangle(); var params = _extend({}, options, { left: rect[0], bottom: rect[3], right: rect[2], top: rect[1] }); - var url = apibase + 'export.php?' + utilQsString(params) + '&ch=' + rules; + var url = _krUrlRoot + 'export.php?' + utilQsString(params) + '&ch=' + rules; _krCache.inflight[tile.id] = d3_json(url, function(err, data) { @@ -343,7 +389,7 @@ export default { // NOTE: This throws a CORS err, but it seems successful. // We don't care too much about the response, so this is fine. - var url = apibase + 'comment.php?' + utilQsString(params); + var url = _krUrlRoot + 'comment.php?' + utilQsString(params); _krCache.inflight[d.id] = d3_request(url) .post(function(err) { delete _krCache.inflight[d.id]; @@ -402,7 +448,7 @@ export default { errorURL: function(error) { - return apibase + 'report_map.php?schema=' + error.schema + '&error=' + error.id; + return _krUrlRoot + 'report_map.php?schema=' + error.schema + '&error=' + error.id; } };