Browse Source

Merge branch 'master' into geo-info

master
parent
commit
201dcaf053
  1. 3
      .gitmodules
  2. 23
      README.md
  3. 7
      asset.php
  4. 19
      conf.php-dist
  5. 3
      doc/Filters.md
  6. 29
      doc/Icons.md
  7. 4
      doc/TwigJS.md
  8. BIN
      img/shadow_left.png
  9. BIN
      img/shadow_top.png
  10. 4
      index.php
  11. 2
      lang/ast.json
  12. 2
      lang/ca.json
  13. 83
      lang/cs.json
  14. 2
      lang/da.json
  15. 19
      lang/de.json
  16. 2
      lang/el.json
  17. 7
      lang/en.json
  18. 15
      lang/es.json
  19. 2
      lang/et.json
  20. 9
      lang/fr.json
  21. 9
      lang/gl.json
  22. 13
      lang/hu.json
  23. 78
      lang/it.json
  24. 78
      lang/ja.json
  25. 55
      lang/nb.json
  26. 78
      lang/nl.json
  27. 50
      lang/oc.json
  28. 51
      lang/pl.json
  29. 15
      lang/pt-br.json
  30. 2
      lang/pt.json
  31. 26
      lang/ro.json
  32. 74
      lang/ru.json
  33. 2
      lang/sr.json
  34. 39
      lang/tr.json
  35. 2
      lang/uk.json
  36. 2
      lib/modulekit/form
  37. 2
      lib/modulekit/lang
  38. 1
      lib/modulekit/mysql-sessions
  39. 7
      locales/nb.js
  40. 7
      locales/tr.js
  41. 3
      modulekit.php
  42. 8647
      package-lock.json
  43. 60
      package.json
  44. 4
      src/CategoryIndex.js
  45. 37
      src/CategoryOverpass.js
  46. 167
      src/CategoryOverpassFilter.js
  47. 2
      src/OpenStreetBrowserLoader.js
  48. 30
      src/RepositoryBase.php
  49. 2
      src/RepositoryGit.php
  50. 7
      src/addCategories.js
  51. 4
      src/defaults.php
  52. 1
      src/export.js
  53. 39
      src/image.js
  54. 8
      src/index.js
  55. 5
      src/map-getMetersPerPixel.js
  56. 110
      src/markers.js
  57. 2
      src/options.js
  58. 2
      src/repositories.php
  59. 2
      src/state.js
  60. 4
      src/tagTranslations.js
  61. 35
      src/twigFunctions.js
  62. 139
      src/wikipedia.js
  63. 51
      style.css

3
.gitmodules

@ -15,3 +15,6 @@
[submodule "lib/modulekit/ajax"]
path = lib/modulekit/ajax
url = https://github.com/plepe/modulekit-ajax.git
[submodule "lib/modulekit/mysql-sessions"]
path = lib/modulekit/mysql-sessions
url = https://github.com/plepe/PHP-MySQL-Sessions.git

23
README.md

@ -65,7 +65,7 @@ File: foo.json
"12": "(node[highway~'^(motorway_junction)$'];way[highway~'^(motorway|trunk)$'];)",
"14": "(node[highway~'^(motorway_junction|mini_roundabout|crossing)$'];way[highway~'^(motorway|trunk|primary)$'];)",
"16": "(node[highway];way[highway];)"
}
},
"feature": {
"style": {
"color": "{% if tags.highway == 'motorway' %}#ff0000{% elseif tags.highway == 'trunk' %}#ff7f00{% elseif tags.highway == 'primary' %}#ffff00{% else %}#0000ff{% endif %}"
@ -87,12 +87,13 @@ The following values are possible for categories (the only mandatory value is qu
* query: either a string or an object of strings with the minimal zoom level as index. Give the Overpass API queries without the header (e.g. `[out:json]` or bounding box) and footer (e.g. `out meta geom` or so).
* minZoom: Show layer only from the given zoom level (default: 14). If `query` is an object and `minZoom` is not set, the lowest zoom level of a query will be used.
* maxZoom: Show layer only up to the given zoom level (default: no limit).
* feature: an object describing how the feature will be formated resp. styled.
* feature: an object describing how the feature will be formatted resp. styled.
* style: a Leaflet style.
* stroke: Whether to draw stroke along the path. Set it to false or empty string to disable borders on polygons or circles. (boolean, true)
* width: Stroke width in pixels (number, 3)
* width: Stroke width, optionally with unit ('px' for width in screen pixels (default) or 'm' for width in world meters). Default: '3px'.
* color: Stroke color (string, '#3388ff')
* opacity: Stroke opacity (number, 1.0)
* offset: Offset stroke to left or right ('px' for width in screen pixels (default) or 'm' for width in world meters). Default: '0px'.
* lineCap: shape at end of the stroke (string, 'round')
* lineJoin: shape at corners of the stroke (string, 'round')
* dashArray: stroke dash pattern (string, null)
@ -115,6 +116,7 @@ The following values are possible for categories (the only mandatory value is qu
* pattern-angleCorrection: degrees (arrowHead and marker only)
* pattern-rotate: false (marker only)
* pattern-path-*: Options for the path, e.g. pattern-path-width, pattern-path-color.
* pane: show vector on the specified pane (usually defined: 'overlayPane' (default), 'hover', 'selected', 'casing')
* title: the title of the feature popup, the object in the list and the details page. (default: localized tags for 'name', 'operator' or 'ref', default: 'unknown')
* body: the body for the feature popup and the details page.
* description: a short description shown in the list next to the title.
@ -136,3 +138,18 @@ With the function `register_hook` you can hook into several functions. The follo
* `show-popup`: called when a popup is being displayed. Parameters: data (see properties in doc/TwigJS.md), category, dom, callback.
* `options_save`: called when options are saved. Parameters: options (the new object), old_options (before save)
* `initFinish`: called when the app initialization finishes
### New locale
* Add language code to the `$languages` array in conf.php (and conf.php-dist)
* Create file `locales/CODE.js` with:
```js
global.locale = {
id: 'CODE',
moment: require('moment'),
// replace 'en' by 'CODE', when a translation for date-format has been submitted
osmDateFormatTemplates: require('openstreetmap-date-format/templates/en')
}
require('moment/locale/CODE')
```
* Run `npm run build-locales`

7
asset.php

@ -15,10 +15,6 @@ if (!array_key_exists($repoId, $allRepositories)) {
$repoData = $allRepositories[$repoId];
$repo = getRepo($repoId, $repoData);
if (!array_key_exists('dir', $_REQUEST)) {
$_REQUEST['dir'] = '.';
}
if (array_key_exists('list', $_REQUEST)) {
$contents = array();
foreach ($repo->scandir($_REQUEST['dir']) as $f) {
@ -32,7 +28,7 @@ if (array_key_exists('list', $_REQUEST)) {
}
else {
$tmpfile = tempnam('/tmp', 'osb-asset-');
$contents = $repo->file_get_contents("{$_REQUEST['dir']}/{$_REQUEST['file']}");
$contents = $repo->file_get_contents((array_key_exists('dir', $_REQUEST) ? "{$_REQUEST['dir']}/" : '') . $_REQUEST['file']);
if ($contents === false) {
Header("HTTP/1.1 401 Permission denied");
@ -44,4 +40,5 @@ else {
}
Header("Content-Type: {$mime_type}; charset=utf-8");
Header("Cache-Control: max-age=86400");
print $contents;

19
conf.php-dist

@ -3,6 +3,7 @@
// repositoryUrl and categoryUrl are twig templates, which take the following input values:
// {{ repositoryId }} id of the repository
// {{ categoryId }} id of the category (not for repositoryUrl)
// {{ branchId }} id of the branch (not for repositoryUrl)
$repositories = array(
'default' => array(
'path' => 'node_modules/openstreetbrowser-categories-main',
@ -10,7 +11,7 @@ $repositories = array(
// public URL of repository
'repositoryUrl' => 'https://github.com/example/categories',
// public URL of source of a category in repository
'categoryUrl' => 'https://github.com/example/categories/tree/master/{{ categoryId }}.json',
'categoryUrl' => 'https://github.com/example/categories/tree/{{ branchId }}/{{ categoryId }}.json',
),
);
@ -26,6 +27,9 @@ $config['categoriesAlwaysReload'] = true;
// (optional) URL, which points to the OpenStreetBrowser Editor
#$config['urlCategoriesEditor'] = 'editor/';
// URL of OpenStreetMap website - change this for other services
$config['urlOpenStreetMap'] = 'https://www.openstreetmap.org';
// URL of the Overpass API
$config['overpassUrl'] = array(
'//overpass-api.de/api/interpreter',
@ -99,11 +103,20 @@ $languages = array(
"it", // Italian
"ja", // Japanese
"nl", // Dutch
"oc", // Occitan
"pl", // Polish
"pt", // Portugese
"pt-br", // Portugese (Brazil)
"pt", // Portuguese
"pt-br", // Portuguese (Brazil)
"ro", // Romanian
"ru", // Russian
"sr", // Serbian
"uk", // Ukrainian
"nb", // Bokmål (Norwegian)
"tr", // Turkish
);
// Uncomment the following lines to use a MYSQL database for session handling.
// Create database table 'sessions' as described in
// https://github.com/plepe/PHP-MySQL-Sessions/blob/master/README.md
#include "lib/modulekit/mysql-sessions/mysql.sessions.php";
#new Session(new PDO('mysql:dbname=DB', 'USER', 'PASSWORD'));

3
doc/Filters.md

@ -28,11 +28,12 @@ Each filter can define the following values:
* key: If not overridden by query, use this key for searching. If not defined, use the filter's ID. Can also be an array with a list of keys. You can use wildcards too, e.g. "name:*" to query all localized name tags.
* op: operator to use (if not overridden by query):
* '=' exact match (default)
* '!=' any value nut this
* '!=' any value but this
* '~' regular expression, case sensitive
* '~i' regular expression, case insensitive
* '!~', '!~i' regular expression, negated
* 'has' query in semicolon-separated lists like `cuisine=kebap;noodles`
* 'has_key_value' query object with a tag with this key
* 'strsearch' query string parts (e.g. "kai keb" would match "Kaiser Kebap") and query character variants (e.g. "cafe" would match "café").
* show_default: if true, this filter will be shown by default, others need to be added via the select box.

29
doc/Icons.md

@ -48,3 +48,32 @@ You can pass URL options to the icon to modify its look. Note that every icon is
<img data-src="temaki:shinto">
<img data-src="temaki:shinto?fill=red">
```
#### Markers
Simple syntax (example: a black line):
```html
<img data-src="marker:line?width=3&amp;color=black">
{{ markerLine({ width: 3, color: 'black' })|raw }}
```
The following marker types are available: line, polygon (a rectangle), circle, pointer
The following style parameters are possible:
* `color`: outline color, default `#000000`.
* `width`: outline width, default `3`.
* `offset`: outline offset, default `0`.
* `fillColor`: color of the fill, default value of `color`. If no `color` is set, use `#f2756a`.
* `fillOpacity`: opacity of the fill, default `0.2`.
* `dashArray`: outline dashes, e.g. `5,5'. Default: `none`.
* `dashOffset`: offset of outline dashes. Default: `0`.
Syntax with multiple symbols (example: a white line with a black casing). Only styles which are listed in the `styles` parameter will be used. Instead of `style:default:width` use `style:width`:
```html
<img data-src="marker:line?styles=casing,default&amp;style:width=2&amp;style:color=white&amp;style:casing:width=4&amp;style:casing:color=black">
{{ markerLine({ styles: 'casing,default', 'style:casing': { color: 'black', width: 4 }, default: { color: 'black', width: 2 }})|raw }}
```
You can use the `evaluate` function, to emulate a fake object (e.g. for map keys). The following example would draw a line, which looks like the symbol which is generated by this category for an OSM object with the tags highway=primary and maxspeed=80:
```html
{{ markerLine(evaluate({ "highway": "primary", "maxspeed": "80" }))|raw }}
```

4
doc/TwigJS.md

@ -62,6 +62,8 @@ There are several extra functions defined for the TwigJS language:
* function `tagsPrefix(tags, prefix)`: return all tags with the specified prefix. The result will be an array with `{ "en": "name:en", "de": "name:de" }` (for the input `{ "name": "foo", "name:en": "english foo", "name:de": "german foo" }` and the prefix "name:").
* function openingHoursState(opening_hours_definition): returns state of object as string: 'closed', 'open' or 'unknown'.
* function colorInterpolate(map, value): interpolates between two or more colors. E.g. `colorInterpolate([ 'red', 'yellow', 'green' ], 0.75)`.
* function enumerate(list): enumerate the given list, e.g. "foo, bar, and bla". Input either an array (`enumerate([ "foo", "bar", "bla" ])`) or a string with `;` as separator (`enumerate("foo;bar;bla")`).
* function debug(): print all arguments to the javascript console (via `console.log()`)
Extra filters:
* filter websiteUrl: return a valid http link. Example: `{{ "www.google.com"|websiteUrl }}` -> "http://www.google.com"; `{{ "https://google.com"|websiteUrl }}` -> "https://google.com"
@ -71,6 +73,8 @@ Extra filters:
* filter `natsort`: Sort an array naturally, see [https://www.npmjs.com/package/natsort](natsort) for details.
* filter `unique`: Remove duplicate elements from an array.
* filter `md5`: calculate md5 hash of a string.
* filter `enumerate`: enumerate the given list, e.g. "foo, bar, and bla". Input either an array (`[ "foo", "bar", "bla" ]|enumerate`) or a string with `;` as separator (`"foo;bar;bla"|enumerate`).
* filter `debug`: print the value (and further arguments) to the javascript console (via `console.log()`)
Notes:
* Variables will automatically be HTML escaped, if not the filter raw is used, e.g.: {{ tags.name|raw }}

BIN
img/shadow_left.png

Before

Width: 5  |  Height: 30  |  Size: 144 B

BIN
img/shadow_top.png

Before

Width: 30  |  Height: 5  |  Size: 151 B

4
index.php

@ -77,7 +77,9 @@ html_export_var(array(
</div>
<div id='footer'>
<ul id='menu'>
<li><a target='_blank' href='https://github.com/plepe/openstreetbrowser'>Code</a></li></ul>
<li><a target='_blank' href='https://github.com/plepe/openstreetbrowser'><?=lang("main:code")?></a></li>
<li><a target='_blank' href='https://wiki.openstreetmap.org/wiki/OpenStreetBrowser'><?=lang("main:about")?></a></li>
</ul>
</div>
</div>
<div id='loadingIndicator'>

2
lang/ast.json

@ -1,5 +1,6 @@
{
"add_filter": "",
"any value": "",
"available_branches": "",
"back": "",
"categories": "",
@ -20,6 +21,7 @@
"header:export": "",
"header:osm_meta": "",
"images": "",
"invalid value": "",
"loading": "",
"main:options": "Opciones",
"main:permalink": "",

2
lang/ca.json

@ -1,5 +1,6 @@
{
"add_filter": "",
"any value": "",
"available_branches": "",
"back": "",
"categories": "",
@ -20,6 +21,7 @@
"header:export": "",
"header:osm_meta": "",
"images": "",
"invalid value": "",
"loading": "",
"main:options": "Opcions",
"main:permalink": "",

83
lang/cs.json

@ -1,48 +1,55 @@
{
"add_filter": "",
"available_branches": "",
"back": "",
"categories": "",
"category-info-tooltip": "",
"closed": "",
"default": "",
"edit": "",
"error": "",
"export-all": "",
"export-prepare": "",
"export:GeoJSON": "",
"export:OSMJSON": "",
"export:OSMXML": "",
"facilities": "",
"filter:title": "",
"filter:type": "",
"header:attributes": "",
"header:export": "",
"header:osm_meta": "",
"images": "",
"loading": "",
"add_filter": "Přidat filtr",
"any value": "jakákoliv hodnota",
"available_branches": "Dostupné větve",
"back": "zpět",
"categories": "Kategorie",
"category-info-tooltip": "Klíče Info a Mapy",
"closed": "zavřeno",
"default": "výchozí",
"edit": "upravit",
"error": "Chyba",
"export-all": "Export všech viditelných prvků mapy",
"export-prepare": "Připravit ke stažení",
"export:GeoJSON": "Stáhnout jako GeoJSON",
"export:OSMJSON": "Stáhnout jako OSM JSON",
"export:OSMXML": "Stáhnout jako OSM XML",
"facilities": "Zařízení",
"filter:title": "Název",
"filter:type": "Typ",
"header:attributes": "Atributy",
"header:export": "Exportovat",
"header:osm_meta": "OSM meta",
"images": "Obrázky",
"invalid value": "neplatná hodnota",
"loading": "Načítání ...",
"main:options": "Nastavení",
"main:permalink": "",
"main:permalink": "Trvalý odkaz",
"more": "více",
"more_categories": "Více kategorií",
"more_categories_gitea": "",
"more_results": "",
"open": "",
"more_categories_gitea": "Tvořte a vylepšujte si kategorie sami!",
"more_results": "Zobrazit více výsledků",
"open": "otevřít",
"options:data_lang": "Jazyk dat",
"options:data_lang:desc": "",
"options:data_lang:desc": "Mnoho funkcí mapy má své jméno (a další značky) přeloženo do různých jazyků (např. 'name:en', 'name:de'). Určete, který jazyk by se měl použít pro zobrazení, nebo „Místní jazyk“, aby se vždy použila nepřekládaná hodnota (např. 'name').",
"options:data_lang:local": "Místní jazyk",
"options:overpassUrl": "",
"options:preferredBaseMap": "",
"options:overpassUrl": "URL OverpassAPI",
"options:preferredBaseMap": "Preferovaná základní mapa",
"options:ui_lang": "Jazyk rozhraní",
"other": "",
"repo-use-as-base": "",
"repositories": "",
"other": "Jiný",
"repo-use-as-base": "Použijte toto úložiště jako základní úložiště",
"repositories": "Úložiště",
"save": "Uložit",
"show details": "",
"toggle_fullscreen": "",
"unknown": "",
"show details": "zobrazit detaily",
"toggle_fullscreen": "Přepnout celoobrazovkový režim",
"unknown": "neznámý",
"unnamed": "nepojmenováno",
"wikipedia:no-url-parse": "",
"zoom_in_appear": "",
"zoom_in_more": ""
"wikipedia:no-url-parse": "Nelze načíst URL Wikipedie",
"zoom_in_appear": "přibližte, aby se zobrazily detaily mapy",
"zoom_in_more": "přibližte pro další funkce mapy",
"cancel": "Zrušit",
"form_element:please_select": "-- vyberte --",
"main:about": "O nás",
"main:code": "Kód",
"options:debug_mode": "Mód ladění"
}

2
lang/da.json

@ -1,5 +1,6 @@
{
"add_filter": "",
"any value": "",
"available_branches": "",
"back": "",
"categories": "",
@ -20,6 +21,7 @@
"header:export": "",
"header:osm_meta": "",
"images": "",
"invalid value": "",
"loading": "",
"main:options": "Indstillinger",
"main:permalink": "",

19
lang/de.json

@ -1,7 +1,9 @@
{
"add_filter": "Filter hinzufügen",
"available_branches": "",
"any value": "",
"available_branches": "Verfügbare Zweige",
"back": "zurück",
"cancel": "Abbrechen",
"categories": "Kategorien",
"category-info-tooltip": "Info & Legende",
"closed": "geschlossen",
@ -16,27 +18,29 @@
"facilities": "Einrichtungen",
"filter:title": "Titel",
"filter:type": "Typ",
"form_element:please_select": "-- bitte wählen --",
"header:attributes": "Attribute",
"header:export": "Export",
"header:osm_meta": "OSM Meta",
"images": "Bilder",
"invalid value": "ungültiger Wert",
"loading": "Laden ...",
"main:options": "Optionen",
"main:permalink": "",
"main:permalink": "Permalink",
"more": "mehr",
"more_categories": "Mehr Kategorien",
"more_categories_gitea": "Erstelle und verbessere Kategorien hier!",
"more_results": "weitere Ergebnisse anzeigen",
"open": "geöffnet",
"options:data_lang": "Datensprache",
"options:data_lang:desc": "",
"options:data_lang:desc": "Bei vielen Kartenelementen wurde der Name (und andere Tags) in verschiedene Sprachen übersetzt (z.B. mit 'name:en', 'name:de'). Gib an, welche Sprache für die Anzeige verwendet werden soll, oder wähle \"Lokale Sprache\", damit immer der nicht übersetzte Wert (z. B. \"name\") verwendet wird.",
"options:data_lang:local": "Lokale Sprache",
"options:overpassUrl": "OverpassAPI Adresse",
"options:preferredBaseMap": "Bevorzugte Hintergrundkarte",
"options:ui_lang": "Anwendungssprache",
"other": "Andere",
"repo-use-as-base": "",
"repositories": "",
"repo-use-as-base": "Verwende dieses Repository als Basis",
"repositories": "Repositorys",
"save": "Speichern",
"show details": "zeige Details",
"toggle_fullscreen": "(De-)aktiviere Vollbildmodus",
@ -44,5 +48,8 @@
"unnamed": "Namenlos",
"wikipedia:no-url-parse": "Konnte Wikipedia Adresse nicht erkennen",
"zoom_in_appear": "Zoome hinein um Kartenobjekte zu sehen",
"zoom_in_more": "Zoome hinein für weitere Kartenobjekte"
"zoom_in_more": "Zoome hinein für weitere Kartenobjekte",
"main:about": "Über",
"main:code": "Code",
"options:debug_mode": "Debug-Modus"
}

2
lang/el.json

@ -1,5 +1,6 @@
{
"add_filter": "",
"any value": "",
"available_branches": "",
"back": "",
"categories": "",
@ -20,6 +21,7 @@
"header:export": "",
"header:osm_meta": "",
"images": "",
"invalid value": "",
"loading": "",
"main:options": "Επιλογές",
"main:permalink": "",

7
lang/en.json

@ -1,7 +1,9 @@
{
"add_filter": "Add filter",
"any value": "any value",
"available_branches": "Available branches",
"back": "back",
"cancel": "Cancel",
"categories": "Categories",
"category-info-tooltip": "Info & Map key",
"closed": "closed",
@ -16,11 +18,15 @@
"facilities": "Facilities",
"filter:title": "Title",
"filter:type": "Type",
"form_element:please_select": "-- please select --",
"header:attributes": "Attributes",
"header:export": "Export",
"header:osm_meta": "OSM Meta",
"images": "Images",
"invalid value": "invalid value",
"loading": "Loading ...",
"main:about": "About",
"main:code": "Code",
"main:options": "Options",
"main:permalink": "Permalink",
"more": "more",
@ -31,6 +37,7 @@
"options:data_lang": "Data language",
"options:data_lang:desc": "Many map features have their name (and other tags) translated to different languages (e.g. with 'name:en', 'name:de'). Specify which language should be used for displaying, or 'Local language' so that always the untranslated value (e.g. 'name') will be used.",
"options:data_lang:local": "Local language",
"options:debug_mode": "Debug mode",
"options:overpassUrl": "OverpassAPI URL",
"options:preferredBaseMap": "Preferred base map",
"options:ui_lang": "Interface language",

15
lang/es.json

@ -1,9 +1,10 @@
{
"add_filter": "Añadir filtro",
"any value": "cualquiera",
"available_branches": "Ramas disponibles",
"back": "atrás",
"categories": "Categorías",
"category-info-tooltip": "",
"category-info-tooltip": "Información y clave del mapa",
"closed": "cerrado",
"default": "predeterminado",
"edit": "editar",
@ -18,8 +19,9 @@
"filter:type": "Tipo",
"header:attributes": "Atributos",
"header:export": "Exportar",
"header:osm_meta": "",
"header:osm_meta": "Metadatos de OSM",
"images": "Imágenes",
"invalid value": "valor incorrecto",
"loading": "Cargando ...",
"main:options": "Opciones",
"main:permalink": "Enlace permanente",
@ -29,7 +31,7 @@
"more_results": "Mostrar más resultados",
"open": "abrir",
"options:data_lang": "Idioma de datos",
"options:data_lang:desc": "",
"options:data_lang:desc": "Muchas funciones del mapa tienen su nombre (y otras etiquetas) traducidos a diferentes idiomas (por ejemplo, con 'name:en', 'name:de'). Especifique qué idioma se debe usar para mostrar, o 'Idioma local' para que siempre se use el valor no traducido (por ejemplo, 'name').",
"options:data_lang:local": "Idioma local",
"options:overpassUrl": "URL de OverpassAPI",
"options:preferredBaseMap": "Mapa base preferido",
@ -44,5 +46,10 @@
"unnamed": "sin nombre",
"wikipedia:no-url-parse": "No se pudo analizar la URL de Wikipedia",
"zoom_in_appear": "acercar para que aparezcan las características del mapa",
"zoom_in_more": "acercar para más características del mapa"
"zoom_in_more": "acercar para más características del mapa",
"cancel": "Cancelar",
"form_element:please_select": "-- Por favor seleccione --",
"main:about": "Acerca de",
"main:code": "Código",
"options:debug_mode": "Menú de depuración"
}

2
lang/et.json

@ -1,5 +1,6 @@
{
"add_filter": "",
"any value": "",
"available_branches": "",
"back": "",
"categories": "",
@ -20,6 +21,7 @@
"header:export": "",
"header:osm_meta": "",
"images": "",
"invalid value": "",
"loading": "",
"main:options": "Valikud",
"main:permalink": "",

9
lang/fr.json

@ -1,5 +1,6 @@
{
"add_filter": "Ajouter un filtre",
"any value": "N'importe quelle valeur",
"available_branches": "Branches disponibles",
"back": "Retour",
"categories": "Catégories",
@ -20,6 +21,7 @@
"header:export": "Export",
"header:osm_meta": "Métadonnées OSM",
"images": "Images",
"invalid value": "valeur invalide",
"loading": "Chargement...",
"main:options": "Options",
"main:permalink": "Permalien",
@ -44,5 +46,10 @@
"unnamed": "sans nom",
"wikipedia:no-url-parse": "Impossible de parser l'URL de Wikipédia",
"zoom_in_appear": "zoomez pour que les éléments de la carte apparaissent",
"zoom_in_more": "zoomez pour afficher plus d'éléments de la carte"
"zoom_in_more": "zoomez pour afficher plus d'éléments de la carte",
"cancel": "Annuler",
"form_element:please_select": "--veuillez sélectionner --",
"main:about": "À propos de",
"main:code": "Code",
"options:debug_mode": "Débogage"
}

9
lang/gl.json

@ -1,5 +1,6 @@
{
"add_filter": "Engadir filtro",
"any value": "calquera valor",
"available_branches": "Redes dispoñíbeis",
"back": "voltar",
"categories": "Categorías",
@ -20,6 +21,7 @@
"header:export": "Exportar",
"header:osm_meta": "OSM Meta",
"images": "Imaxes",
"invalid value": "valor non válido",
"loading": "Estase a cargar...",
"main:options": "Opcións",
"main:permalink": "Permalink (ligazón permanente)",
@ -44,5 +46,10 @@
"unnamed": "sen nome",
"wikipedia:no-url-parse": "Non foi posíbel analizar a URL da Wikipedia",
"zoom_in_appear": "achegar a vista para amosar os elementos do mapa",
"zoom_in_more": "achegar a vista para amosar máis elementos do mapa"
"zoom_in_more": "achegar a vista para amosar máis elementos do mapa",
"cancel": "Desbotar",
"form_element:please_select": "-- por favor, escolle --",
"main:about": "Sobre",
"main:code": "Código",
"options:debug_mode": "Modo depuración"
}

13
lang/hu.json

@ -1,7 +1,8 @@
{
"add_filter": "Szűrő hozzáadása",
"available_branches": "",
"back": "Vissza",
"any value": "bármilyen érték",
"available_branches": "Elérhető elágazások",
"back": "vissza",
"categories": "Kategóriák",
"category-info-tooltip": "Információk és jelmagyarázat",
"closed": "Lezárva",
@ -20,6 +21,7 @@
"header:export": "Exportálás",
"header:osm_meta": "OSM metaadatok",
"images": "Képek",
"invalid value": "érvénytelen érték",
"loading": "Betöltés…",
"main:options": "Beállítások",
"main:permalink": "Állandó link (permalink)",
@ -44,5 +46,10 @@
"unnamed": "Névtelen",
"wikipedia:no-url-parse": "Nem sikerült felismerni a Wikipédia-webcímet",
"zoom_in_appear": "Nagyítson az objektumok megjelenítéséhez",
"zoom_in_more": "Nagyítson további objektumok megjelenítéséhez"
"zoom_in_more": "Nagyítson további objektumok megjelenítéséhez",
"cancel": "Mégse",
"form_element:please_select": "-- Kérjük, válasszon --",
"main:about": "Névjegy",
"main:code": "Kód",
"options:debug_mode": "Hibakeresési mód"
}

78
lang/it.json

@ -1,48 +1,50 @@
{
"add_filter": "",
"available_branches": "",
"back": "",
"categories": "",
"category-info-tooltip": "",
"closed": "",
"default": "",
"edit": "",
"error": "",
"export-all": "",
"export-prepare": "",
"export:GeoJSON": "",
"export:OSMJSON": "",
"export:OSMXML": "",
"facilities": "",
"filter:title": "",
"filter:type": "",
"header:attributes": "",
"header:export": "",
"header:osm_meta": "",
"images": "",
"loading": "",
"add_filter": "Aggiungi filtro di ricerca",
"any value": "un valore qualsiasi",
"available_branches": "Rami disponibili",
"back": "indietro",
"categories": "Categorie",
"category-info-tooltip": "Info & Map_key",
"closed": "chiuso",
"default": "predefinito",
"edit": "edita",
"error": "Errore",
"export-all": "Esporta tutte le caratteristiche visibili della mappa",
"export-prepare": "Preparare il download",
"export:GeoJSON": "Download in formato GeoJSON",
"export:OSMJSON": "Downlaod in formato OSM JSON",
"export:OSMXML": "Download in formato OSM XML",
"facilities": "Servizi",
"filter:title": "Titolo",
"filter:type": "Tipologia",
"header:attributes": "Attributi",
"header:export": "Esporta",
"header:osm_meta": "Meta OSM",
"images": "Immagini",
"invalid value": "valore non valido",
"loading": "Caricamento ...",
"main:options": "Opzioni",
"main:permalink": "",
"main:permalink": "Link permanente Permalink",
"more": "altri",
"more_categories": "Altre categorie",
"more_categories_gitea": "",
"more_results": "",
"open": "",
"more_categories_gitea": "Crea &amp;1 ed arrichiisci le categorie!",
"more_results": "Mostra ulteriori risultati",
"open": "apri",
"options:data_lang": "Lingua dei dati",
"options:data_lang:desc": "",
"options:data_lang:desc": "Molte caratteristiche della mappa hanno nome (ed altre etichette proprie) tradotti in lingue differenti (mediante 'name:en' , 'name:de', etc. etc.). Va specificata quale lingua adottare nella visualizzazione, oppure utilizzare 'Local language' in modo che venga sempre usato il valore originario non tradotto (quello impostato con 'name').",
"options:data_lang:local": "Lingua del tuo browser",
"options:overpassUrl": "",
"options:preferredBaseMap": "",
"options:overpassUrl": "URL OverpassAPI",
"options:preferredBaseMap": "Sfondo (basemap) preferito",
"options:ui_lang": "Lingua dell'interfaccia",
"other": "",
"repo-use-as-base": "",
"repositories": "",
"other": "Altro",
"repo-use-as-base": "Usare questo repertorio come repertorio base",
"repositories": "Repertori",
"save": "Salva",
"show details": "",
"toggle_fullscreen": "",
"unknown": "",
"show details": "mostra dettagli",
"toggle_fullscreen": "Attiva/disattiva modalità Schermo intero",
"unknown": "sconosciuto",
"unnamed": "privo di nome",
"wikipedia:no-url-parse": "",
"zoom_in_appear": "",
"zoom_in_more": ""
"wikipedia:no-url-parse": "Non è possibile decifrare la URL Wikipedia",
"zoom_in_appear": "ingrandire la mappa per mostrare le caratteristiche",
"zoom_in_more": "ingrandire la mappa per mostrare ulteriori caratteristiche"
}

78
lang/ja.json

@ -1,48 +1,50 @@
{
"add_filter": "",
"available_branches": "",
"back": "",
"categories": "",
"category-info-tooltip": "",
"closed": "",
"default": "",
"edit": "",
"error": "",
"export-all": "",
"export-prepare": "",
"export:GeoJSON": "",
"export:OSMJSON": "",
"export:OSMXML": "",
"facilities": "",
"filter:title": "",
"filter:type": "",
"header:attributes": "",
"header:export": "",
"header:osm_meta": "",
"images": "",
"loading": "",
"add_filter": "フィルタを追加",
"any value": "",
"available_branches": "利用可能なブランチ",
"back": "戻る",
"categories": "カテゴリ",
"category-info-tooltip": "情報 & 地図キー",
"closed": "クローズ",
"default": "デフォルト",
"edit": "編集",
"error": "エラー",
"export-all": "地図上にある地物を全てエクスポート",
"export-prepare": "ダウンロードの準備",
"export:GeoJSON": "GeoJSONとしてダウンロード",
"export:OSMJSON": "OSM JSONとしてダウンロード",
"export:OSMXML": "OSM XMLとしてダウンロード",
"facilities": "施設",
"filter:title": "タイトル",
"filter:type": "種類",
"header:attributes": "属性",
"header:export": "エクスポート",
"header:osm_meta": "OSM メタ",
"images": "画像",
"invalid value": "",
"loading": "読み込み中...",
"main:options": "オプション設定",
"main:permalink": "",
"main:permalink": "パーマリンク",
"more": "もっと",
"more_categories": "カテゴリを一覧から追加",
"more_categories_gitea": "",
"more_results": "",
"open": "",
"more_categories_gitea": "カテゴリを自分自身で作成 &amp; 改善しよう!",
"more_results": "結果をもっと表示",
"open": "開く",
"options:data_lang": "データ表示",
"options:data_lang:desc": "",
"options:data_lang:desc": "多くの地物にはname(及びその他のタグ)があり、様々な言語(例:'name:en'や'name:de')に翻訳されます。表示に使う言語を、あるいは常に未翻訳の値(例:'name')を表示したければ'ブラウザの設定言語'を指定してください。",
"options:data_lang:local": "ブラウザの設定言語",
"options:overpassUrl": "",
"options:preferredBaseMap": "",
"options:overpassUrl": "OverpassAPI のURL",
"options:preferredBaseMap": "ベース地図選択",
"options:ui_lang": "インタフェース表示",
"other": "",
"repo-use-as-base": "",
"repositories": "",
"other": "その他",
"repo-use-as-base": "このリポジトリをベースリポジトリとして使う",
"repositories": "リポジトリ",
"save": "保存",
"show details": "",
"toggle_fullscreen": "",
"unknown": "",
"show details": "詳細を表示",
"toggle_fullscreen": "全画面モード切替",
"unknown": "不明",
"unnamed": "nameなし",
"wikipedia:no-url-parse": "",
"zoom_in_appear": "",
"zoom_in_more": ""
"wikipedia:no-url-parse": "Wikipedia URLをパースできません",
"zoom_in_appear": "ズームインして地物を表示させる",
"zoom_in_more": "ズームインしてもっと地物を表示させる"
}

55
lang/nb.json

@ -0,0 +1,55 @@
{
"add_filter": "Legg til filter",
"any value": "hvilken som helst verdi",
"available_branches": "Tilgjengelige grener",
"back": "tilbake",
"cancel": "Avbryt",
"categories": "Kategorier",
"category-info-tooltip": "Info & Kart-nøkkelverdi",
"closed": "lukket",
"default": "standard",
"edit": "rediger",
"error": "Feil",
"export-all": "Eksporter alle synlige kartobjekter",
"export-prepare": "Forbered nedlasting",
"export:GeoJSON": "Last ned som GeoJSON",
"export:OSMJSON": "Last ned som OSM-JSON",
"export:OSMXML": "Last ned som OSM-XML",
"facilities": "Fasiliteter",
"filter:title": "Tittel",
"filter:type": "Type",
"form_element:please_select": "-- vennligst velg --",
"header:attributes": "Attributter",
"header:export": "Eksporter",
"header:osm_meta": "OSM-meta",
"images": "Bilder",
"invalid value": "ugyldig verdi",
"loading": "Laster ...",
"main:about": "Om",
"main:code": "Kode",
"main:options": "Innstillinger",
"main:permalink": "Permalink",
"more": "mer",
"more_categories": "Flere kategorier",
"more_categories_gitea": "Lag &amp; forbedre kategoriene selv!",
"more_results": "Vis flere resultater",
"open": "åpen",
"options:data_lang": "Dataspråk",
"options:data_lang:desc": "Mange kartobjekter har navnet sitt (og andre egenskaper) oversatt til andre språk (eks. med 'name:en', 'name:no'). Spesifiser hvilket språk som skal brukes for å vise objektene, eller velg 'Lokalt språk' slik at den uoversatte verdien (eks. 'name') skal brukes.",
"options:data_lang:local": "Lokalt språk",
"options:debug_mode": "Debug-modus",
"options:overpassUrl": "OverpassAPI-URL",
"options:preferredBaseMap": "Foretrukket grunnkart",
"options:ui_lang": "Grensesnittspråk",
"other": "Andre",
"repo-use-as-base": "Bruk dette repo-området som grunn-repo",
"repositories": "Repoer",
"save": "Lagre",
"show details": "vis detaljer",
"toggle_fullscreen": "Slå av/på fullskjermsmodus",
"unknown": "ukjent",
"unnamed": "navnløs",
"wikipedia:no-url-parse": "Kunne ikke håndtere Wikipedia-URLen",
"zoom_in_appear": "zoom inn for å se kartobjekter",
"zoom_in_more": "zoom inn for flere kartobjekter"
}

78
lang/nl.json

@ -1,48 +1,50 @@
{
"add_filter": "",
"available_branches": "",
"back": "",
"categories": "",
"category-info-tooltip": "",
"closed": "",
"default": "",
"edit": "",
"error": "",
"export-all": "",
"export-prepare": "",
"export:GeoJSON": "",
"export:OSMJSON": "",
"export:OSMXML": "",
"facilities": "",
"filter:title": "",
"filter:type": "",
"header:attributes": "",
"header:export": "",
"header:osm_meta": "",
"images": "",
"loading": "",
"add_filter": "Filter toevoegen",
"any value": "om het even welke waarde",
"available_branches": "Beschikbare delen",
"back": "terug",
"categories": "Categorieën",
"category-info-tooltip": "Info en kaart sleutel",
"closed": "gesloten",
"default": "standaard",
"edit": "bewerk",
"error": "Fout",
"export-all": "Exporteer alle zichtbare kaartelementen",
"export-prepare": "Bereid download voor",
"export:GeoJSON": "Download als GeoJSON",
"export:OSMJSON": "Download als OSM JSON",
"export:OSMXML": "Download als OSM XML",
"facilities": "Uitrusting",
"filter:title": "Titel",
"filter:type": "Type",
"header:attributes": "Attributen",
"header:export": "Exporteer",
"header:osm_meta": "OSM Meta",
"images": "Afbeeldingen",
"invalid value": "ongeldige waarde",
"loading": "Laden...",
"main:options": "Opties",
"main:permalink": "",
"main:permalink": "Permalink",
"more": "meer",
"more_categories": "Meer categorieën",
"more_categories_gitea": "",
"more_results": "",
"open": "",
"more_categories_gitea": "Creëer &amp; verbeter zelf categorieën!",
"more_results": "Geef meer resultaten weer",
"open": "open",
"options:data_lang": "Taal voor data",
"options:data_lang:desc": "",
"options:data_lang:desc": "Van veel kaartelementen zijn hun naam (en andere tags) vertaald naar verschillende talen (bv. met 'name:en, 'name:nl'). Geef aan welk taal gebruikt moet worden voor de weergave, of 'Lokale taal', zodat altijd de niet-vertaalde waarde (bv. 'naam') gebruikt wordt.",
"options:data_lang:local": "Lokale taal",
"options:overpassUrl": "",
"options:preferredBaseMap": "",
"options:overpassUrl": "OverpassAPI URL",
"options:preferredBaseMap": "Voorkeur basiskaart",
"options:ui_lang": "Interfacetaal",
"other": "",
"repo-use-as-base": "",
"repositories": "",
"other": "Andere",
"repo-use-as-base": "Gebruik deze repository als basis repository",
"repositories": "Repositories",
"save": "Opslaan",
"show details": "",
"toggle_fullscreen": "",
"unknown": "",
"show details": "geef details weer",
"toggle_fullscreen": "Wisselen van volledig scherm weergave",
"unknown": "onbekend",
"unnamed": "naamloos",
"wikipedia:no-url-parse": "",
"zoom_in_appear": "",
"zoom_in_more": ""
"wikipedia:no-url-parse": "De Wikipedia URL kan niet verwerkt worden",
"zoom_in_appear": "zoom in op de kaart om kaartelementen weer te geven",
"zoom_in_more": "zoom in om voor meer kaartelementen"
}

50
lang/oc.json

@ -0,0 +1,50 @@
{
"add_filter": "Ajustar un filtre de recèrca",
"any value": "Que valor que siegue",
"available_branches": "Brancas disponiblas",
"back": "Tornar",
"categories": "Categorias",
"category-info-tooltip": "Info & Legenda",
"closed": "Plegat",
"default": "Predefinit",
"edit": "editar",
"error": "Error",
"export-all": "Exportar totei leis objèctes cartografiats visibles",
"export-prepare": "Preparar la descarga",
"export:GeoJSON": "Format GeoJSON",
"export:OSMJSON": "Format OSM JSON",
"export:OSMXML": "Format OSM XML",
"facilities": "Servicis",
"filter:title": "Títol",
"filter:type": "Tipe",
"header:attributes": "Atributs",
"header:export": "Exportar",
"header:osm_meta": "Metadadas OSM",
"images": "Imatges",
"invalid value": "Valors non validas",
"loading": "A se cargar...",
"main:options": "Opcions",
"main:permalink": "Permaliame",
"more": "mai",
"more_categories": "Mai de categorias",
"more_categories_gitea": "Creatz e melhoratz vos lei categorias !",
"more_results": "Mostrar mai de resultats",
"open": "obrir",
"options:data_lang": "Lenga dei dadas",
"options:data_lang:desc": "Fòrça elements de la mapa an lo nom (emai d'autreis etiquetas) traduits en divèrsei lengas (exemple : 'name:oc', 'name:br'). Indicatz la lenga d'emplegar premiera, ò l'expression 'Lenga locala' per forçar l'emplec de la lenga de vòstre navigator.",
"options:data_lang:local": "Lenga locala",
"options:overpassUrl": "URL OverpassAPI",
"options:preferredBaseMap": "Fons de mapa preferit",
"options:ui_lang": "Lenga de l'interfàcia",
"other": "Autrei",
"repo-use-as-base": "Emplegar aqueste repertòri per depaus de basa",
"repositories": "Repertòris",
"save": "Sauvagardar",
"show details": "monstrar per lo menut",
"toggle_fullscreen": "Activar/ Desactivar lo plen escran",
"unknown": "non conoissut, -da(s)",
"unnamed": "ges de nom",
"wikipedia:no-url-parse": "Impossible de deschifrar l'URL de Wikipédia",
"zoom_in_appear": "regrandir per mostrar leis elements de la mapa",
"zoom_in_more": "regrandir per monstrar mai d'elements de la mapa"
}

51
lang/pl.json

@ -1,48 +1,55 @@
{
"add_filter": "",
"available_branches": "",
"add_filter": "Dodaj filtr",
"any value": "dowolna wartość",
"available_branches": "Dostępne gałęzie",
"back": "Wstecz",
"categories": "Kategorie",
"category-info-tooltip": "",
"category-info-tooltip": "Informacje i legenda mapy",
"closed": "Zamknięte",
"default": "Domyślne",
"edit": "Edycja",
"error": "Błąd",
"export-all": "",
"export-prepare": "",
"export:GeoJSON": "",
"export:OSMJSON": "",
"export:OSMXML": "",
"facilities": "",
"filter:title": "",
"filter:type": "",
"header:attributes": "",
"export-all": "Eksport wszystkich widzialnych cech mapy",
"export-prepare": "Przygotowanie pobrania",
"export:GeoJSON": "Pobierz jako GeoJSON",
"export:OSMJSON": "Pobierz jako OSM JSON",
"export:OSMXML": "Pobierz jako OSM XML",
"facilities": "Udogodnienia",
"filter:title": "Tytuł",
"filter:type": "Rodzaj",
"header:attributes": "Atrybuty",
"header:export": "Eksport",
"header:osm_meta": "",
"header:osm_meta": "Metadane OSM",
"images": "Obrazy",
"loading": "Wczytywanie",
"invalid value": "nieprawidłowa wartość",
"loading": "Wczytywanie…",
"main:options": "Opcje",
"main:permalink": "",
"main:permalink": "Odnośnik bezpośredni",
"more": "Więcej",
"more_categories": "Więcej kategorii",
"more_categories_gitea": "",
"more_categories_gitea": "Samemu utwórz i dostosuj kategorie!",
"more_results": "Więcej wyników",
"open": "Otwórz",
"options:data_lang": "Język danych",
"options:data_lang:desc": "",
"options:data_lang:desc": "Wiele elementów mapy ma przetłumaczone nazwy (i inne znaczniki) na różne języki (np. posiada „name:en”, „name:de”). Określ język, który ma być używany do wyświetlania, lub wybierz „Język lokalny”, aby zawsze używana była nieprzetłumaczona wartość (np. „nazwa”).",
"options:data_lang:local": "Język lokalny",
"options:overpassUrl": "",
"options:preferredBaseMap": "",
"options:overpassUrl": "Adres URL do OverpassAPI",
"options:preferredBaseMap": "Preferencje mapy bazowej",
"options:ui_lang": "Język interfejsu",
"other": "Inne",
"repo-use-as-base": "",
"repo-use-as-base": "Użyj tego repozytorium jako bazowego",
"repositories": "Repozytoria",
"save": "Zapisz",
"show details": "Pokaż szczegóły",
"toggle_fullscreen": "Przełącz pełny ekran",
"unknown": "Nieznane",
"unnamed": "Nienazwane",
"wikipedia:no-url-parse": "",
"wikipedia:no-url-parse": "Nie można przetworzyć adresu URL Wikipedii",
"zoom_in_appear": "Powiększ widoczność",
"zoom_in_more": "Powiększ bardziej"
"zoom_in_more": "Powiększ bardziej",
"cancel": "Anuluj",
"form_element:please_select": "– proszę wybrać –",
"main:about": "Informacje",
"main:code": "Kod",
"options:debug_mode": "Tryb debugowania"
}

15
lang/pt-br.json

@ -1,7 +1,9 @@
{
"add_filter": "",
"add_filter": "Adicionar filtro",
"any value": "qualquer valor",
"available_branches": "Redes disponíveis",
"back": "voltar",
"cancel": "Cancelar",
"categories": "Categorias",
"category-info-tooltip": "Info & Legenda",
"closed": "fechado",
@ -14,13 +16,17 @@
"export:OSMJSON": "Baixar como OSMJSON",
"export:OSMXML": "Baixar como OSMXML",
"facilities": "Instalações",
"filter:title": "",
"filter:type": "",
"filter:title": "Título",
"filter:type": "Tipo",
"form_element:please_select": "-- favor selecione --",
"header:attributes": "Atributos",
"header:export": "Exportar",
"header:osm_meta": "OSM Meta",
"images": "Imagens",
"invalid value": "Valor inválido",
"loading": "Carregando...",
"main:about": "Sobre",
"main:code": "Código-fonte",
"main:options": "Opções",
"main:permalink": "Link permanente",
"more": "mais",
@ -29,8 +35,9 @@
"more_results": "Exibir mais resultados",
"open": "abrir",
"options:data_lang": "Língua dos dados",
"options:data_lang:desc": "Muitos elementos do mapa possuem seus nomes (e outras etiquetas) traduzidas para línguas diferentes (p.ex. com 'name:en', 'name:de'). Especificar qual língua deve ser usada para exibição, ou 'Língua local' de forma que sempre os valores não tranduzidos (p.ex. 'name') sejam usados.",
"options:data_lang:desc": "Muitos recursos do mapa têm seu nome (e outras tags) traduzido para idiomas diferentes (por exemplo, com 'name: en', 'name: de'). Especifique o idioma que deve ser usado para exibição ou \"Idioma local\" para que sempre o valor não traduzido (por exemplo, \"nome\") seja usado.",
"options:data_lang:local": "Língua local",
"options:debug_mode": "Modo depuração",
"options:overpassUrl": "URL do OverpassAPI",
"options:preferredBaseMap": "Mapa-base preferido",
"options:ui_lang": "Língua da interface",

2
lang/pt.json

@ -1,5 +1,6 @@
{
"add_filter": "",
"any value": "",
"available_branches": "",
"back": "voltar",
"categories": "",
@ -20,6 +21,7 @@
"header:export": "Exportar",
"header:osm_meta": "OSM Meta",
"images": "Imagens",
"invalid value": "",
"loading": "A carregar...",
"main:options": "Opções",
"main:permalink": "",

26
lang/ro.json

@ -1,13 +1,14 @@
{
"add_filter": "",
"any value": "orice valoare",
"available_branches": "",
"back": "",
"categories": "",
"back": "înapoi",
"categories": "Categorii",
"category-info-tooltip": "",
"closed": "",
"default": "",
"closed": "închis",
"default": "Implicit",
"edit": "",
"error": "",
"error": "Eroare",
"export-all": "",
"export-prepare": "",
"export:GeoJSON": "",
@ -19,15 +20,16 @@
"header:attributes": "",
"header:export": "",
"header:osm_meta": "",
"images": "",
"loading": "",
"images": "Imagini",
"invalid value": "",
"loading": "Se încarcă ...",
"main:options": "Optiuni",
"main:permalink": "",
"more": "Mai mult",
"more_categories": "Mai multe categorii",
"more_categories_gitea": "",
"more_results": "",
"open": "",
"open": "deschide",
"options:data_lang": "Limba date",
"options:data_lang:desc": "",
"options:data_lang:local": "Limba locala",
@ -38,11 +40,13 @@
"repo-use-as-base": "",
"repositories": "",
"save": "Salveaza",
"show details": "",
"show details": "arată detalii",
"toggle_fullscreen": "",
"unknown": "",
"unknown": "necunoscut",
"unnamed": "anonim",
"wikipedia:no-url-parse": "",
"zoom_in_appear": "",
"zoom_in_more": ""
"zoom_in_more": "",
"cancel": "Renunță",
"main:about": "Despre"
}

74
lang/ru.json

@ -1,48 +1,50 @@
{
"add_filter": "",
"add_filter": "Добавить фильтр",
"any value": "любое значение",
"available_branches": "",
"back": "",
"categories": "",
"category-info-tooltip": "",
"back": "назад",
"categories": "Категории",
"category-info-tooltip": "Информация и легенда",
"closed": "",
"default": "",
"edit": "",
"error": "",
"export-all": "",
"export-prepare": "",
"export:GeoJSON": "",
"export:OSMJSON": "",
"export:OSMXML": "",
"facilities": "",
"filter:title": "",
"filter:type": "",
"header:attributes": "",
"header:export": "",
"header:osm_meta": "",
"images": "",
"loading": "",
"default": "по умолчанию",
"edit": "изменить",
"error": "Ошибка",
"export-all": "Экспортировать все видимые объекты карты",
"export-prepare": "Скачать",
"export:GeoJSON": "Скачать как GeoJSON",
"export:OSMJSON": "Скачать как OSM JSON",
"export:OSMXML": "Скачать как OSM XML",
"facilities": "Удобства",
"filter:title": "Название",
"filter:type": "Тип",
"header:attributes": "Атрибуты",
"header:export": "Экспорт",
"header:osm_meta": "OSM Meta",
"images": "Изображения",
"invalid value": "неверное значение",
"loading": "Загрузка...",
"main:options": "Настройки",
"main:permalink": "",
"main:permalink": "Постоянная ссылка",
"more": "Ещё",
"more_categories": "Больше категорий",
"more_categories_gitea": "",
"more_results": "",
"open": "",
"more_categories_gitea": "Создавайте и улучшайте категории самостоятельно!",
"more_results": "Больше результатов",
"open": "открыть",
"options:data_lang": "Язык информации на карте",
"options:data_lang:desc": "",
"options:data_lang:desc": "Названия многих элементов карты (и другие теги), переведены на разные языки (например, с помощью «name: en», «name: de»). Укажите, какой язык следует использовать для отображения, или «Местный язык», чтобы всегда использовалось непереведенное значение (например, «name»).",
"options:data_lang:local": "Определить язык автоматически",
"options:overpassUrl": "",
"options:preferredBaseMap": "",
"options:overpassUrl": "OverpassAPI URL",
"options:preferredBaseMap": "Предпочитаемая карта",
"options:ui_lang": "Язык интерфейса",
"other": "",
"repo-use-as-base": "",
"repositories": "",
"other": "Прочие",
"repo-use-as-base": "Использовать этот репозиторий как базовый",
"repositories": "Репозитории",
"save": "Сохранить",
"show details": "",
"toggle_fullscreen": "",
"unknown": "",
"show details": "подробнее",
"toggle_fullscreen": "Полноэкранный режим",
"unknown": "неизвестно",
"unnamed": "безымянный",
"wikipedia:no-url-parse": "",
"zoom_in_appear": "",
"zoom_in_more": ""
"wikipedia:no-url-parse": "Не удалось разобрать Wikipedia URL",
"zoom_in_appear": "приблизьте, для отображения объектов карты",
"zoom_in_more": "приблизьте, для большего количества объектов карты"
}

2
lang/sr.json

@ -1,5 +1,6 @@
{
"add_filter": "",
"any value": "",
"available_branches": "",
"back": "",
"categories": "",
@ -20,6 +21,7 @@
"header:export": "",
"header:osm_meta": "",
"images": "",
"invalid value": "",
"loading": "",
"main:options": "Опције",
"main:permalink": "",

39
lang/tr.json

@ -0,0 +1,39 @@
{
"add_filter": "Filtre ekle",
"any value": "herhangi bir değer",
"back": "geri",
"cancel": "İptal",
"categories": "Kategories",
"category-info-tooltip": "Bilgi & Harita anahtarı",
"closed": "kapalı",
"default": "varsayılan",
"edit": "düzenle",
"error": "Hata",
"export:GeoJSON": "GeoJSON İndir",
"export:OSMJSON": "OSM JSON İndir",
"filter:title": "Başlık",
"filter:type": "Tip",
"form_element:please_select": "-- lütfen seçiniz --",
"header:attributes": "Öznitelikler",
"header:export": "Dışa aktar",
"header:osm_meta": "OSM Meta",
"main:about": "Hakkında",
"main:code": "Kod",
"main:options": "Seçenekler",
"open": "aç",
"options:data_lang": "Veri dili",
"options:data_lang:local": "Yerel dil",
"other": "Diğer",
"export-all": "Görüntülenen harita detaylarını dışa aktar",
"export-prepare": "İndirmeyi hazırla",
"facilities": "Tesisler",
"images": "Görüntüler",
"invalid value": "geçersiz değer",
"loading": "Yükleniyor ...",
"main:permalink": "Kalıcı Bağlantı",
"more_categories": "Daha fazla kategori",
"options:ui_lang": "Arayüz dili",
"save": "Sakla",
"show details": "detayları göster",
"toggle_fullscreen": "Tam ekran modu"
}

2
lang/uk.json

@ -1,5 +1,6 @@
{
"add_filter": "",
"any value": "",
"available_branches": "",
"back": "",
"categories": "",
@ -20,6 +21,7 @@
"header:export": "",
"header:osm_meta": "",
"images": "",
"invalid value": "",
"loading": "",
"main:options": "Налаштування",
"main:permalink": "",

2
lib/modulekit/form

@ -1 +1 @@
Subproject commit 5198dc8e00d46893bd93ed3b3d71c8ea7994e1c2
Subproject commit 5e8e05f5b0aa7ed4cb3d25b83d5806d2f0ab697f

2
lib/modulekit/lang

@ -1 +1 @@
Subproject commit 40d2e911bf43708b26aea633e53cd3d6e6884312
Subproject commit 0dc7f5348115a6aae1d87afdc3c4f9a5408627a3

1
lib/modulekit/mysql-sessions

@ -0,0 +1 @@
Subproject commit 662ff647a4f0abb794a2e39cc94021413e4bbb13

7
locales/nb.js

@ -0,0 +1,7 @@
global.locale = {
id: 'nb',
moment: require('moment'),
osmDateFormatTemplates: require('openstreetmap-date-format/templates/en')
}
require('moment/locale/nb')

7
locales/tr.js

@ -0,0 +1,7 @@
global.locale = {
id: 'tr',
moment: require('moment'),
osmDateFormatTemplates: require('openstreetmap-date-format/templates/en')
}
require('moment/locale/tr')

3
modulekit.php

@ -11,6 +11,7 @@ $depend = array(
);
$include = array(
'php' => array(
'src/defaults.php',
'src/options.php',
'src/language.php',
'src/ip-location.php',
@ -25,4 +26,4 @@ $include = array(
'style.css',
),
);
$version = "4.5";
$version = "4.7";

8647
package-lock.json
File diff suppressed because it is too large
View File

60
package.json

@ -1,74 +1,50 @@
{
"name": "openstreetbrowser",
"version": "4.5.0",
"version": "4.7.0",
"description": "A re-make of the famous OpenStreetBrowser (pure JS, using Overpass API)",
"main": "src/export.js",
"repository": "https://github.com/plepe/openstreetbrowser",
"author": "Stephan Bösch-Plepelits <skunk@xover.mud.at>",
"license": "GPL-3.0",
"dependencies": {
"@fortawesome/fontawesome-free": "^5.8.1",
"@babel/cli": "^7.7.7",
"@babel/core": "^7.7.7",
"@babel/preset-env": "^7.7.7",
"@fortawesome/fontawesome-free": "^5.12.0",
"@mapbox/maki": "^5.0.0",
"async": "^2.5.0",
"async-foreach": "^0.1.3",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babelify": "^8.0.0",
"color-interpolate": "^1.0.2",
"babelify": "^10.0.0",
"color-interpolate": "^1.0.5",
"event-emitter": "^0.3.5",
"file-saver": "^2.0.0",
"i18next-client": "^1.11.4",
"ip-location": "^1.0.1",
"json-multiline-strings": "^0.1.0",
"leaflet": "^1.0.3",
"leaflet": "^1.6.0",
"leaflet-geosearch": "^2.4.0",
"leaflet-polylineoffset": "^1.1.0",
"leaflet-textpath": "https://github.com/makinacorpus/Leaflet.TextPath#leaflet0.8-dev",
"leaflet-textpath": "git+https://github.com/makinacorpus/Leaflet.TextPath.git#leaflet0.8-dev",
"leaflet.locatecontrol": "^0.61.0",
"leaflet.polylinemeasure": "https://github.com/ppete2/Leaflet.PolylineMeasure.git",
"leaflet.polylinemeasure": "git+https://github.com/ppete2/Leaflet.PolylineMeasure.git",
"md5": "^2.2.1",
"modulekit-tabs": "^0.2.1",
"modulekit-tabs": "^0.2.2",
"moment": "^2.18.1",
"natsort": "^1.0.6",
"opening_hours": "^3.5.0",
"openstreetbrowser-categories-main": "https://github.com/plepe/openstreetbrowser-categories-main",
"openstreetbrowser-categories-main": "git+https://github.com/plepe/openstreetbrowser-categories-main.git",
"openstreetmap-date-format": "^0.2.0",
"openstreetmap-date-parser": "^0.1.0",
"openstreetmap-tag-translations": "https://github.com/plepe/openstreetmap-tag-translations",
"overpass-layer": "^2.3.0",
"openstreetmap-tag-translations": "git+https://github.com/plepe/openstreetmap-tag-translations.git",
"overpass-layer": "^2.5.0",
"query-string": "^5.0.0",
"sheet-router": "^4.2.3",
"temaki": "^1.0.0",
"temaki": "^1.9.0",
"weight-sort": "^1.3.0"
},
"browserify": {
"transform": [
[
"babelify",
{
"presets": [
[
"env",
{
"targets": {
"browsers": [
"last 2 versions",
"> 0.5%",
"safari >= 7",
"ie >= 11"
]
}
}
]
]
}
]
]
},
"scripts": {
"test": "mocha --bail",
"build": "npm run build-locales && browserify -g browserify-css src/index.js -o dist/tmp1.js && babel --presets env dist/tmp1.js > dist/tmp2.js && mv dist/tmp2.js dist/openstreetbrowser.js && rm dist/tmp1.js",
"build": "npm run build-locales && browserify -g browserify-css src/index.js -o dist/tmp1.js && babel --presets @babel/preset-env dist/tmp1.js > dist/tmp2.js && mv dist/tmp2.js dist/openstreetbrowser.js && rm dist/tmp1.js",
"build-locales": "for i in `ls locales/` ; do browserify locales/$i -o dist/locale-$i ; done",
"watch": "npm run build-locales && watchify --debug -g browserify-css src/index.js -o dist/openstreetbrowser.js -v",
"prepublish": "npm run build",
@ -76,8 +52,8 @@
},
"devDependencies": {
"browserify": "^14.4.0",
"browserify-css": "^0.14.0",
"leaflet-polylinedecorator": "https://github.com/plepe/Leaflet.PolylineDecorator.git",
"browserify-css": "^0.15.0",
"leaflet-polylinedecorator": "git+https://github.com/plepe/Leaflet.PolylineDecorator.git",
"mocha": "^5.2.0",
"standard": "^10.0.2",
"watchify": "^3.9.0"

4
src/CategoryIndex.js

@ -11,9 +11,9 @@ function CategoryIndex (options, data, repository) {
this.childrenDoms = {}
this.childrenCategories = null
this._loadChildrenCategories(function (err) {
this._loadChildrenCategories((err) => {
if (err) {
console.log('error loading child categories:', err)
console.log('Category "' + this.id + '": error loading child categories:', err)
}
})
}

37
src/CategoryOverpass.js

@ -218,9 +218,35 @@ CategoryOverpass.prototype.updateAssets = function (div) {
}
})
}
} else if (src.match(/^(marker):.*/)) {
let m = src.match(/^(marker):([a-z0-9-_]*)(?:\?(.*))?$/)
if (m) {
let span = document.createElement('span')
img.parentNode.insertBefore(span, img)
img.parentNode.removeChild(img)
i--
let param = m[3] ? qs(m[3]) : {}
if (param.styles) {
let newParam = { styles: param.styles }
for (let k in param) {
let m = k.match(/^(style|style:.*)?:([^:]*)$/)
if (m) {
if (!(m[1] in newParam)) {
newParam[m[1]] = {}
}
newParam[m[1]][m[2]] = param[k]
}
}
param = newParam
}
console.log(param)
span.innerHTML = markers[m[2]](param)
}
} else if (!src.match(/^(https?:|data:|\.|\/)/)) {
img.setAttribute('src', (typeof openstreetbrowserPrefix === 'undefined' ? './' : openstreetbrowserPrefix) +
'asset.php?repo=' + this.options.repositoryId + '&file=' + encodeURIComponent(img.getAttribute('src')))
'asset.php?repo=' + this.options.repositoryId + '&file=' + encodeURIComponent(img.getAttribute('data-src') || img.getAttribute('src')))
}
}
}
@ -407,7 +433,10 @@ CategoryOverpass.prototype.updateInfo = function () {
'const': this.data.const
}
if (this.map) {
data.map = { zoom: map.getZoom() }
data.map = {
zoom: this.map.getZoom(),
metersPerPixel: this.map.getMetersPerPixel()
}
}
this.domInfo.innerHTML = this.templateInfo.render(data)
this.updateAssets(this.domInfo)
@ -464,7 +493,7 @@ CategoryOverpass.prototype.show = function (id, options, callback) {
var preferredZoom = data.data.preferredZoom || 16
var maxZoom = this.map.getZoom()
maxZoom = maxZoom > preferredZoom ? maxZoom : preferredZoom
this.map.flyToBounds(data.object.bounds.toLeaflet(), {
this.map.flyToBounds(data.object.bounds.toLeaflet({ shiftWorld: this.layer.getShiftWorld() }), {
maxZoom: maxZoom
})
}
@ -538,7 +567,7 @@ CategoryOverpass.prototype.updatePopupContent = function (object, popup) {
}
var footerContent = '<li><a class="showDetails" href="#' + this.id + '/' + id_with_sublayer + '/details">' + lang('show details') + '</a></li>'
footerContent += '<li><a target="_blank" class="editLink" href="https://www.openstreetmap.org/edit?editor=id&' + object.object.type + '=' + object.object.osm_id + '">' + lang('edit') + '</a></li>'
footerContent += '<li><a target="_blank" class="editLink" href="' + config.urlOpenStreetMap + '/edit?editor=id&' + object.object.type + '=' + object.object.osm_id + '">' + lang('edit') + '</a></li>'
footer.innerHTML = footerContent
}

167
src/CategoryOverpassFilter.js

@ -1,5 +1,6 @@
const OverpassLayer = require('overpass-layer')
const tabs = require('modulekit-tabs')
const natsort = require('natsort')
const state = require('./state')
const Filter = require('overpass-frontend').Filter
@ -43,7 +44,7 @@ class CategoryOverpassFilter {
if ('name' in f && typeof f.name === 'string') {
global.currentCategory = this.master
let t = OverpassLayer.twig.twig({ data: f.name, autoescape: true })
f.name = t.render({}).toString()
f.name = decodeHTML(t.render({}).toString())
} else if (!('name' in f)) {
f.name = lang('tag:' + k)
}
@ -69,48 +70,66 @@ class CategoryOverpassFilter {
let k = option.value
f.values[k] = {}
Array.from(option.attributes).forEach(attr => {
f.values[k][attr.name] = attr.value
})
if (option.textContent) {
f.values[k].name = option.textContent
}
if (option.hasAttribute('query')) {
f.values[k].query = option.getAttribute('query')
}
}
}
if (Array.isArray(f.values) && f.valueName) {
let newValues = {}
f.values.forEach(value => {
newValues[value] = valueNameTemplate.render({ value }).toString()
newValues[value] = decodeHTML(valueNameTemplate.render({ value }).toString())
})
f.values = newValues
} else if (typeof f.values === 'object') {
for (var k1 in f.values) {
if (typeof f.values[k1] === 'string') {
let t = OverpassLayer.twig.twig({ data: f.values[k1], autoescape: true })
f.values[k1] = t.render({}).toString()
f.values[k1] = decodeHTML(t.render({}).toString())
} else if (typeof f.values[k1] === 'object') {
if (!('name' in f.values[k1])) {
f.values[k1].name = valueNameTemplate.render({ value: k1 }).toString()
f.values[k1].name = decodeHTML(valueNameTemplate.render({ value: k1 }).toString())
} else if (f.values[k1].name) {
let t = OverpassLayer.twig.twig({ data: f.values[k1].name, autoescape: true })
f.values[k1].name = t.render({}).toString()
f.values[k1].name = decodeHTML(t.render({}))
}
}
}
}
if (!('sort' in f) || (f.sort === 'natsort')) {
let v = {}
let sorter = natsort({ insensitive: true })
let keys = Object.keys(f.values)
keys
.sort((a, b) => {
let weight = (f.values[a].weight || 0) - (f.values[b].weight || 0)
if (weight !== 0) {
return weight
}
return sorter(f.values[a].name, f.values[b].name)
})
.forEach(k => { v[k] = f.values[k] })
f.values = v
}
}
}
let masterOptions = {}
let masterOptions = {
'change_on_input': true
}
if (Object.keys(this.data).length > 1) {
masterOptions = {
'type': 'form_chooser',
'button:add_element': '-- ' + lang('add_filter') + ' --',
'order': false,
'change_on_input': true
}
masterOptions['type'] = 'form_chooser'
masterOptions['button:add_element'] = '-- ' + lang('add_filter') + ' --'
masterOptions['order'] = false
}
this.formFilter = new form('filter-' + this.master.id, this.data, masterOptions)
@ -120,7 +139,6 @@ class CategoryOverpassFilter {
this.applyParam(param)
this.master.layer.check_update_map()
state.update()
}.bind(this)
@ -135,67 +153,74 @@ class CategoryOverpassFilter {
}
applyParam (param) {
this.additionalFilter = []
let kvFilter = []
this.additionalFilter = Object.keys(param).map(k => {
let values = param[k]
let d = this.data[k]
for (var k in param) {
if (param[k] === null) {
continue
if (values === null) {
return null
}
var d = this.data[k]
if ('values' in d && param[k] in d.values && typeof d.values[param[k]] === 'object' && 'query' in d.values[param[k]]) {
let f = new Filter(d.values[param[k]].query)
this.additionalFilter.push(f.def)
continue
} else if (d.queryTemplate) {
let f = new Filter(d.queryTemplate.render({ value: param[k] }).toString())
this.additionalFilter.push(f.def)
continue
if (!Array.isArray(values)) {
values = [ values ]
}
var v = {
key: 'key' in d ? d.key : k,
value: param[k],
op: '='
}
let ret = values.map(value => {
if ('values' in d && value in d.values && typeof d.values[value] === 'object' && 'query' in d.values[value]) {
let f = new Filter(d.values[value].query)
return f.def
} else if (d.queryTemplate) {
let f = new Filter(decodeHTML(d.queryTemplate.render({ value: value }).toString()))
return f.def
}
if ('op' in d) {
if (d.op === 'has_key_value') {
v = {
key: param[k],
op: 'has_key'
var v = {
key: 'key' in d ? d.key : k,
value: value,
op: '='
}
if ('op' in d) {
if (d.op === 'has_key_value') {
v = {
key: value,
op: 'has_key'
}
} else {
v.op = d.op
}
} else {
v.op = d.op
}
}
if (Array.isArray(v.key)) {
v = {
"or": v.key.map(
key => {
let v1 = { key, value: v.value, op: v.op }
if (Array.isArray(v.key)) {
v = {
"or": v.key.map(
key => {
let v1 = { key, value: v.value, op: v.op }
let m = key.match(/^(.*)\*(.*)/)
if (m) {
v1.key = '^' + m[1] + '.*' + m[2]
v1.keyRegexp = true
}
let m = key.match(/^(.*)\*(.*)/)
if (m) {
v1.key = '^' + m[1] + '.*' + m[2]
v1.keyRegexp = true
return [ v1 ]
}
return [ v1 ]
}
)
)
}
}
}
kvFilter.push(v)
}
return [ v ]
}).filter(f => f) // remove null values
if (kvFilter.length) {
this.additionalFilter.push(kvFilter)
}
switch (ret.length) {
case 0:
return null
case 1:
return ret[0]
default:
return { or: ret }
}
}).filter(f => f) // remove null values
if (this.additionalFilter.length === 0) {
this.additionalFilter = []
@ -205,7 +230,7 @@ class CategoryOverpassFilter {
this.additionalFilter = { and: this.additionalFilter }
}
this.master.layer.options.queryOptions.filter = this.additionalFilter
this.master.layer.setFilter(this.additionalFilter)
if (!this.tabFilter.isSelected()) {
this.tabFilter.select()
@ -232,3 +257,15 @@ register_hook('category-overpass-init', (category) => {
new CategoryOverpassFilter(category)
}
})
function decodeHTML (str) {
if (typeof str === 'undefined') {
return '-- undefined --'
}
return str
.replace(/&#039;/g, '\'')
.replace(/&quot;/g, '"')
.replace(/&gt;/g, '>')
.replace(/&lt;/g, '<')
}

2
src/OpenStreetBrowserLoader.js

@ -55,7 +55,7 @@ OpenStreetBrowserLoader.prototype.getCategory = function (id, options, callback)
}
if (!(ids.entityId in repoData.categories)) {
return callback(new Error('category not defined'), null)
return callback(new Error('category "' + ids.entityId + '" not defined'), null)
}
this.getCategoryFromData(ids.id, opt, repoData.categories[ids.entityId], function (err, category) {

30
src/RepositoryBase.php

@ -34,9 +34,36 @@ class RepositoryBase {
return $data;
}
function unfoldCategories (&$data, &$categories=null) {
if ($categories === null) {
$categories = &$data['categories'];
}
foreach ($categories as $id => $_category) {
$category = &$categories[$id];
if (is_array($category) && $category['type'] === 'index') {
foreach ($category['subCategories'] as $subIndex => $_subCategory) {
$subCategory = &$category['subCategories'][$subIndex];
if (array_key_exists('type', $subCategory)) {
$data['categories'][$subCategory['id']] = $subCategory;
$this->unfoldCategories($data, $subCategory);
$category['subCategories'][$subIndex] = array(
'id' => $subCategory['id']
);
}
}
}
}
}
function updateLang (&$data, $options) {
$lang = array_key_exists('lang', $options) ? $options['lang'] : 'en';
$this->unfoldCategories($data);
if (!is_array($data['lang'])) {
$data['lang'] = array();
}
@ -52,7 +79,7 @@ class RepositoryBase {
);
}
}
elseif (array_key_exists('name', $category)) {
elseif (is_array($category) && array_key_exists('name', $category)) {
if (array_key_exists($lang, $category['name'])) {
$name = $category['name'][$lang];
}
@ -67,6 +94,7 @@ class RepositoryBase {
$data['categories'][$id]['name'] = array($lang => $name);
}
}
}

2
src/RepositoryGit.php

@ -24,7 +24,7 @@ class RepositoryGit extends RepositoryBase {
}
function timestamp () {
$ts = (int)shell_exec("cd " . escapeShellArg($this->path) . "; git log -1 {$this->branchEsc} --pretty=format:%ct");
$ts = (int)shell_exec("cd " . escapeShellArg($this->path) . "; git log -1 --all --pretty=format:%ct");
return $ts;
}

7
src/addCategories.js

@ -17,6 +17,9 @@ function addCategoriesShow (repo, options={}) {
[ repoId, branchId ] = repo.split(/~/)
}
if (!branchId) {
branchId = 'master'
}
content.innerHTML = '<h3>' + lang('more_categories') + '</h3>' + '<i class="fa fa-spinner fa-pulse fa-fw"></i> ' + lang('loading')
@ -128,7 +131,7 @@ function addCategoriesShow (repo, options={}) {
}
let header = document.createElement('h3')
header.innerHTML = lang(repo ? 'repositories' : 'categories') + ':'
header.innerHTML = lang(repo ? 'categories' : 'repositories') + ':'
content.appendChild(header)
var ul = document.createElement('ul')
@ -163,7 +166,7 @@ function addCategoriesShow (repo, options={}) {
var editLink = null
if (repo && categoryUrl) {
editLink = document.createElement('a')
editLink.href = categoryUrl.render({ repositoryId: repo, categoryId: id })
editLink.href = categoryUrl.render({ repositoryId: repoId, categoryId: id, branchId: branchId })
}
if (!repo && repositoryUrl) {
editLink = document.createElement('a')

4
src/defaults.php

@ -0,0 +1,4 @@
<?php
if (!array_key_exists('urlOpenStreetMap', $config)) {
$config['urlOpenStreetMap'] = 'https://www.openstreetmap.org';
}

1
src/export.js

@ -2,6 +2,7 @@ require('./twigFunctions')
require('./tagTranslations')
require('./markers')
require('./category.css')
require('./CategoryOverpassFilter')
module.exports = {
CategoryIndex: require('./CategoryIndex'),

39
src/image.js

@ -9,7 +9,11 @@ function showImage (image, dom) {
dom.appendChild(div)
}
function showWikimediaImage (image, dom) {
function showWikimediaImage (image, options, dom) {
if (!options.size) {
options.size = 800
}
httpGet(
'https://commons.wikimedia.org/wiki/File:' + encodeURIComponent(image.id),
{
@ -20,13 +24,18 @@ function showWikimediaImage (image, dom) {
return
}
let m = result.body.match('img .* src="([^"]+)" .* data-file-width="([0-9]+)" data-file-height="([0-9]+)"')
let src = m[1]
let m = result.body.match(/<a href="([^"]+\/)([0-9]+)(px-[^"\/]+)" class="mw-thumbnail-link"/)
if (m) {
let src = m[1] + options.size + m[3]
let srcset = m[1] + options.size + m[3] + ' 1x, ' +
m[1] + Math.ceil(options.size * 1.5) + m[3] + ' 1.5x, ' +
m[1] + Math.ceil(options.size * 2) + m[3] + ' 2x'
var div = document.createElement('div')
div.innerHTML = '<a target="_blank" href="https://commons.wikimedia.org/wiki/File:' + encodeURIComponent(image.id) + '"><img src="' + src + '"/></a>'
var div = document.createElement('div')
div.innerHTML = '<a target="_blank" href="https://commons.wikimedia.org/wiki/File:' + encodeURIComponent(image.id) + '"><img src="' + src + '" srcset="' + srcset + '"/></a>'
dom.appendChild(div)
dom.appendChild(div)
}
}
)
}
@ -37,7 +46,7 @@ function show (img, options, div) {
switch (img.type) {
case 'wikimedia':
showWikimediaImage(img, div)
showWikimediaImage(img, options, div)
break
case 'url':
showImage(img, div)
@ -51,6 +60,7 @@ register_hook('show-details', function (data, category, dom, callback) {
div.className = 'images loading'
var imageWrapper
var nextImageWrapper = document.createElement('div')
let options
dom.appendChild(div)
@ -85,9 +95,13 @@ register_hook('show-details', function (data, category, dom, callback) {
imageWrapper.className = 'imageWrapper'
div.appendChild(imageWrapper)
options = {
size: Math.max(imageWrapper.offsetWidth, imageWrapper.offsetHeight)
}
showTimer = window.setInterval(showNext, 5000)
show(img, {}, imageWrapper)
show(img, options, imageWrapper)
loadNext()
})
@ -100,7 +114,7 @@ register_hook('show-details', function (data, category, dom, callback) {
return console.log("Can't load next image", err)
}
show(img, {}, nextImageWrapper)
show(img, options, nextImageWrapper)
})
}
@ -149,7 +163,12 @@ register_hook('show-popup', function (data, category, dom, callback) {
imageWrapper.className = 'imageWrapper'
div.appendChild(imageWrapper)
show(img, {}, imageWrapper)
let options = {
size: 150
}
console.log(options)
show(img, options, imageWrapper)
callback(null)
})

8
src/index.js

@ -11,6 +11,7 @@ global.OpenStreetBrowserLoader = OpenStreetBrowserLoader
require('./CategoryIndex')
require('./CategoryOverpass')
require('./category.css')
const mapMetersPerPixel = require('./map-getMetersPerPixel')
global.map = null
global.baseCategory = null
@ -46,6 +47,9 @@ window.onload = function () {
var initState = config.defaultView
map = L.map('map')
map.getMetersPerPixel = mapMetersPerPixel.bind(map)
map.attributionControl.setPrefix('<a target="_blank" href="https://wiki.openstreetmap.org/wiki/OpenStreetBrowser">OpenStreetBrowser</a>')
// due to php export, options may be an array -> fix
if (Array.isArray(options)) {
@ -59,6 +63,8 @@ window.onload = function () {
map.createPane('selected')
map.getPane('selected').style.zIndex = 498
map.createPane('casing')
map.getPane('casing').style.zIndex = 399
}
function onload2 (initState) {
@ -328,7 +334,7 @@ window.showDetails = function (data, category) {
dd = document.createElement('dd')
a = document.createElement('a')
a.appendChild(document.createTextNode(data.object.type + '/' + data.object.osm_id))
a.href = 'https://openstreetmap.org/' + data.object.type + '/' + data.object.osm_id
a.href = config.urlOpenStreetMap + '/' + data.object.type + '/' + data.object.osm_id
a.target = '_blank'
dd.appendChild(a)

5
src/map-getMetersPerPixel.js

@ -0,0 +1,5 @@
function getMetersPerPixel () {
return 40075016.686 * Math.abs(Math.cos(this.getCenter().lat / 180 * Math.PI)) / Math.pow(2, this.getZoom() + 8)
}
module.exports = getMetersPerPixel

110
src/markers.js

@ -1,11 +1,12 @@
var OverpassLayer = require('overpass-layer')
var parseLength = require('overpass-layer/src/parseLength')
function cssStyle (style) {
var ret = ''
let ret = ''
if ('color' in style) {
ret += 'stroke: ' + style.color + ';'
}
ret += 'stroke-width: ' + ('width' in style ? style.width : '3') + ';'
ret += 'stroke-width: ' + parseLength('width' in style ? style.width : '3', global.map.getMetersPerPixel()) + ';'
if ('dashArray' in style) {
ret += 'stroke-dasharray: ' + style.dashArray + ';'
}
@ -15,9 +16,6 @@ function cssStyle (style) {
if ('dashOffset' in style) {
ret += 'stroke-dashoffset: ' + style.dashOffset + ';'
}
if ('offset' in style) {
ret += 'stroke-offset: ' + style.dashOffset + ';'
}
if ('fillColor' in style) {
ret += 'fill: ' + style.fillColor + ';'
} else if ('color' in style) {
@ -35,22 +33,15 @@ function cssStyle (style) {
}
function markerLine (data) {
var ret = '<svg anchorX="13" anchorY="8" width="25" height="15">'
let styles = parseOptions(data)
if (!('styles' in data)) {
data = {
style: data,
styles: [ 'default' ]
}
}
let ret = '<svg anchorX="13" anchorY="8" width="25" height="15">'
for (var i = 0; i < data.styles.length; i++) {
var k = data.styles[i]
var style = k === 'default' ? data.style : data['style:' + k]
var y = 8.0 + parseFloat('offset' in style ? style.offset : 0)
styles.forEach(style => {
let y = 8.0 + parseLength('offset' in style ? style.offset : 0, global.map.getMetersPerPixel())
ret += '<line x1="0" y1="' + y + '" x2="25" y2="' + y + '" style="' + cssStyle(style) + '"/>'
}
})
ret += '</svg>'
@ -58,42 +49,81 @@ function markerLine (data) {
}
function markerPolygon (data) {
var ret = '<svg anchorX="13" anchorY="8" width="25" height="25">'
let ret = '<svg anchorX="13" anchorY="8" width="25" height="25">'
if (!('styles' in data)) {
data = {
style: data,
styles: [ 'default' ]
}
}
for (var i = 0; i < data.styles.length; i++) {
var k = data.styles[i]
var style = k === 'default' ? data.style : data['style:' + k]
let styles = parseOptions(data)
styles.forEach(style => {
ret += '<rect x="3" y="3" width="18" height="18" style="' + cssStyle(style) + '"/>'
}
})
ret += '</svg>'
return ret
}
function markerCircle (style) {
var fillColor = 'fillColor' in style ? style.fillColor : '#f2756a'
var color = 'color' in style ? style.color : '#000000'
var width = 'width' in style ? style.width : 1
var radius = 'radius' in style ? style.radius : 12
function markerCircle (data) {
let styles = parseOptions(data)
let c = styles
.map(style => (style.size || style.radius || 12) + (style.width / 2))
.sort()[0]
let ret = '<svg anchorX="' + (c + 0.5) + ' anchorY="' + (c + 0.5) + '" width="' + (c * 2) + '" height="' + (c * 2) + '">'
return '<svg anchorX="13" anchorY="13" width="25" height="25"><circle cx="12.5" cy="12.5" r=' + radius + ' style="stroke: ' + color + '; stroke-width: ' + width + '; fill: ' + fillColor + ';"/></svg>'
styles.forEach(style => {
ret += '<circle cx="' + c + '" cy="' + c + '" r="' + (style.radius || 12) + '" style="' + cssStyle(style) + '"/>'
})
ret += '</svg>'
return ret
}
function markerPointer (style) {
var fillColor = 'fillColor' in style ? style.fillColor : '#f2756a'
var color = 'color' in style ? style.color : '#000000'
var width = 'width' in style ? style.width : 1
function markerPointer (data) {
let ret = '<svg anchorX="13" anchorY="45" width="25" height="45" signAnchorX="0" signAnchorY="-31">'
let styles = parseOptions(data)
styles.forEach(style => {
ret += '<path d="M0.5,12.5 A 12,12 0 0 1 24.5,12.5 C 24.5,23 13,30 12.5,44.5 C 12,30 0.5,23 0.5,12.5" style="' + cssStyle(style) + '"/>'
})
ret += '</svg>'
return ret
}
function parseOptions (data) {
if (!data || !('style' in data) && !('styles' in data)) {
let ret = [
{ fillColor: '#f2756a', color: '#000000', width: 1, radius: 12, fillOpacity: 1 },
]
if (data && data.color) {
ret[0].fillColor = data.color
ret[0].fillOpacity = 0.2
}
if (data) for (let k in data) {
ret[0][k] = data[k]
}
return ret
}
if (!('styles' in data)) {
data = {
style: data,
styles: [ 'default' ]
}
}
if (typeof data.styles === 'string') {
data.styles = data.styles.split(/,/g)
}
return '<svg anchorX="13" anchorY="45" width="25" height="45" signAnchorX="0" signAnchorY="-31"><path d="M0.5,12.5 A 12,12 0 0 1 24.5,12.5 C 24.5,23 13,30 12.5,44.5 C 12,30 0.5,23 0.5,12.5" style="stroke: ' + color + '; stroke-width: ' + width + '; fill: ' + fillColor + ';"/></svg>'
return data.styles.map(k => (k === 'default' ? data.style : data['style:' + k]) || {})
}
OverpassLayer.twig.extendFunction('markerLine', markerLine)

2
src/options.js

@ -20,7 +20,7 @@ moduleOptions.open = function () {
var def = {
'debug': {
'type': 'boolean',
'name': 'Debug mode',
'name': lang('options:debug_mode'),
'weight': 10,
'reloadOnChange': true
}

2
src/repositories.php

@ -31,7 +31,7 @@ function getRepositories () {
if (array_key_exists('url', $repositoriesGitea)) {
$r['repositoryUrl'] = "{$repositoriesGitea['url']}/{{ repositoryId }}";
$r['categoryUrl'] = "{$repositoriesGitea['url']}/{{ repositoryId }}/src/{{ categoryId }}.json";
$r['categoryUrl'] = "{$repositoriesGitea['url']}/{{ repositoryId }}/src/branch/{{ branchId }}/{{ categoryId }}.json";
}
$result["{$f1}/{$f2id}"] = $r;

2
src/state.js

@ -17,7 +17,7 @@ function get () {
// location
if (typeof map.getZoom() !== 'undefined') {
var center = map.getCenter()
var center = map.getCenter().wrap()
var zoom = map.getZoom()
state.lat = center.lat

4
src/tagTranslations.js

@ -26,6 +26,10 @@ OverpassLayer.twig.extendFunction('isTranslated', function (str) {
return tagTranslationsIsTranslated(str)
})
OverpassLayer.twig.extendFunction('repoTrans', function (str) {
if (!global.currentCategory.repository) {
return str
}
let lang = global.currentCategory.repository.lang
return str in lang ? lang[str] : str
})

35
src/twigFunctions.js

@ -44,7 +44,7 @@ OverpassLayer.twig.extendFilter('websiteUrl', function (value) {
return 'http://' + value
})
OverpassLayer.twig.extendFilter('matches', function (value, match) {
if (value === null) {
if (value === null || typeof value === 'undefined') {
return false
}
@ -93,10 +93,35 @@ OverpassLayer.twig.extendFunction('evaluate', function (tags) {
var d = global.currentCategory.layer.mainlayer.evaluate(ob)
return d
})
OverpassLayer.twig.extendFunction('enumerate', function (value) {
let list = value.split(/,/)
if (list.length > 1) {
return list.slice(0, -1).join(lang_str.enumerate_join) + lang_str.enumerate_last + list.slice(-1)[0]
function enumerate (list) {
if (typeof list === 'string') {
list = list.split(/;/g)
}
if (list.length > 2) {
let result = lang_str.enumerate_start.replace('{0}', list[0]).replace('{1}', list[1])
for (let i = 2; i < list.length - 1; i++) {
result = lang_str.enumerate_middle.replace('{0}', result).replace('{1}', list[i])
}
return lang_str.enumerate_end.replace('{0}', result).replace('{1}', list[list.length - 1])
}
else if (list.length == 2) {
return lang_str.enumerate_2.replace('{0}', list[0]).replace('{1}', list[1])
}
else if (list.length > 0) {
return list[0]
}
return ''
}
OverpassLayer.twig.extendFunction('enumerate', (list) => enumerate(list))
OverpassLayer.twig.extendFilter('enumerate', (list) => enumerate(list))
OverpassLayer.twig.extendFunction('debug', function () {
console.log.apply(null, arguments)
})
OverpassLayer.twig.extendFilter('debug', function (value, param) {
console.log.apply(null, [ value, ...param ])
return value
})

139
src/wikipedia.js

@ -43,7 +43,7 @@ function prepare (div) {
stripLinks(p)
// first image
var imgs = div.getElementsByTagName('img')
var imgs = content.getElementsByTagName('img')
for (i = 0; i < imgs.length; i++) {
var img = imgs[i]
@ -125,89 +125,64 @@ register_hook('show-details', function (data, category, dom, callback) {
div.className = 'wikipedia'
if ('wikipedia' in ob.tags) {
found++
foundPrefixes.push('')
showWikipedia(ob.tags.wikipedia, div, done)
ob.tags.wikipedia.split(/;/g).forEach(value => {
found++
showWikipedia(value, div, done)
})
}
for (k in ob.tags) {
m = k.match(/^(.*):wikipedia$/)
if (m) {
let prefix = m[1]
h = document.createElement('h4')
h.appendChild(document.createTextNode(lang('tag:' + m[1])))
h.appendChild(document.createTextNode(lang('tag:' + prefix)))
div.appendChild(h)
found++
foundPrefixes.push(m[1])
showWikipedia(ob.tags[k], div, done)
foundPrefixes.push(prefix)
ob.tags[k].split(/;/g).forEach(value => {
found++
showWikipedia(value, div, done)
})
}
m = k.match(/^((.*):)?wikipedia:(.*)$/)
if (m) {
if (typeof m[1] === 'undefined' && foundPrefixes.indexOf('') !== -1) {
let prefix = m[1]
if (typeof prefix === 'undefined' && foundPrefixes.indexOf('') !== -1) {
continue
}
if (foundPrefixes.indexOf(m[1]) !== -1) {
if (foundPrefixes.indexOf(prefix) !== -1) {
continue
}
if (m[1]) {
if (prefix) {
h = document.createElement('h4')
h.appendChild(document.createTextNode(lang('tag:' + m[1])))
h.appendChild(document.createTextNode(lang('tag:' + prefix)))
div.appendChild(h)
}
found++
foundPrefixes.push(m[1])
showWikipedia(m[3] + ':' + ob.tags[k], div, done)
foundPrefixes.push(prefix)
(m[3] + ':' + ob.tags[k]).split(/;/g).forEach(value => {
found++
showWikipedia(value, div, done)
})
}
}
if (ob.tags.wikidata && foundPrefixes.indexOf('') === -1) {
found++
foundPrefixes.push('')
wikidata.load(ob.tags.wikidata, function (err, result) {
var x
if (err) {
return done(err)
}
if (!result.sitelinks) {
return done(new Error('No Wikipedia links defined for Wikidata'))
}
if (options.data_lang + 'wiki' in result.sitelinks) {
x = result.sitelinks[options.data_lang + 'wiki']
return showWikipedia(options.data_lang + ':' + x.title, div, done)
}
for (k in result.sitelinks) {
if (k === 'commonswiki') {
continue
}
x = result.sitelinks[k]
m = k.match(/^(.*)wiki$/)
return showWikipedia(m[1] + ':' + x.title, div, done)
}
done()
})
}
for (k in ob.tags) {
m = k.match(/^(.*):wikidata$/)
if (m) {
ob.tags.wikidata.split(/;/g).forEach(value => {
found++
if (foundPrefixes.indexOf(m[1]) !== -1) {
continue
}
foundPrefixes.push(m[1])
wikidata.load(ob.tags[k], function (prefix, err, result) {
wikidata.load(value, function (err, result) {
var x
if (err) {
@ -215,13 +190,9 @@ register_hook('show-details', function (data, category, dom, callback) {
}
if (!result.sitelinks) {
return done()
return done(new Error('No Wikipedia links defined for Wikidata'))
}
h = document.createElement('h4')
h.appendChild(document.createTextNode(lang('tag:' + prefix)))
div.appendChild(h)
if (options.data_lang + 'wiki' in result.sitelinks) {
x = result.sitelinks[options.data_lang + 'wiki']
return showWikipedia(options.data_lang + ':' + x.title, div, done)
@ -238,7 +209,54 @@ register_hook('show-details', function (data, category, dom, callback) {
}
done()
}.bind(this, m[1]))
})
})
}
for (k in ob.tags) {
m = k.match(/^(.*):wikidata$/)
if (m) {
let prefix = m[1]
found++
if (foundPrefixes.indexOf(prefix) !== -1) {
continue
}
foundPrefixes.push(prefix)
h = document.createElement('h4')
h.appendChild(document.createTextNode(lang('tag:' + prefix)))
div.appendChild(h)
ob.tags[k].split(/;/g).forEach(value => {
wikidata.load(value, (err, result) => {
var x
if (err) {
return done(err)
}
if (!result.sitelinks) {
return done()
}
if (options.data_lang + 'wiki' in result.sitelinks) {
x = result.sitelinks[options.data_lang + 'wiki']
return showWikipedia(options.data_lang + ':' + x.title, div, done)
}
for (k in result.sitelinks) {
if (k === 'commonswiki') {
continue
}
x = result.sitelinks[k]
m = k.match(/^(.*)wiki$/)
return showWikipedia(m[1] + ':' + x.title, div, done)
}
done()
})
})
}
}
@ -282,7 +300,8 @@ function showWikipedia (tagValue, dom, callback) {
div.innerHTML = text
block.appendChild(div)
block.className = ''
block.removeChild(l)
block.className = 'clearfix'
callback(err)
})

51
style.css

@ -39,8 +39,7 @@ a:active {
bottom: 0;
width: 5px;
z-index: 10000;
background-image: url(img/shadow_left.png);
background-repeat: repeat-y;
background: linear-gradient(to right, #5656566f, #56565600);
}
#sidebar {
@ -197,8 +196,7 @@ a:active {
bottom: auto;
height: 5px;
width: auto;
background-image: url(img/shadow_top.png);
background-repeat: repeat-x;
background: linear-gradient(to bottom, #5656566f, #56565600);
}
#sidebar > #content {
overflow: visible;
@ -209,39 +207,15 @@ a:active {
}
}
@media all and (max-width: 500px) and (max-height: 500px) {
@media all and (max-width: 500px) and (max-height: 675px) {
#sidebar {
height: 220px;
height: 40%;
}
#map {
top: 220px;
top: 40%;
}
#mapShadow {
top: 221px;
}
}
@media all and (max-width: 500px) and (max-height: 460px) {
#sidebar {
height: 200px;
}
#map {
top: 200px;
}
#mapShadow {
top: 201px;
}
}
@media all and (max-width: 500px) and (max-height: 420px) {
#sidebar {
height: 180px;
}
#map {
top: 180px;
}
#mapShadow {
top: 181px;
top: calc(40% + 1px);
}
}
@ -379,8 +353,13 @@ a:active {
margin-left: 0.5em;
margin-bottom: 0.5em;
}
.wikipedia div {
.wikipedia > h4 {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.wikipedia > div {
text-align: justify;
margin-bottom: 0.5em;
}
#contentDetails h3 {
border-bottom: 1px solid black;
@ -431,3 +410,9 @@ a:active {
.tabs-section > form > span.form_element_form_chooser {
border: none;
}
.clearfix::after {
content: '';
clear: both;
display: table;
}
Loading…
Cancel
Save