diff --git a/.forgejo/workflows/mapgen-openaddresses.yml b/.forgejo/workflows/mapgen-openaddresses.yml new file mode 100644 index 000000000..91415d8ea --- /dev/null +++ b/.forgejo/workflows/mapgen-openaddresses.yml @@ -0,0 +1,117 @@ +name: mapgen-openaddresses +on: + workflow_dispatch: # Manual trigger + inputs: + oa-collection-id: + description: 'OpenAddresses collection ID (e.g. 6 for Canada)' + required: true + default: '6' + type: string + +env: + DEBIAN_FRONTEND: noninteractive + TZ: Etc/UTC + ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }} + ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }} + OA_API_TOKEN: ${{ secrets.OA_API_TOKEN }} + +jobs: + update-openaddresses: + name: Update OpenAddresses data + runs-on: mapfilemaker + container: + image: codeberg.org/comaps/maps_generator:f6d53d54f794 + volumes: + - /mnt/4tbexternal/:/mnt/4tbexternal/ + - /mnt/4tbexternal/osm-planet:/home/planet + concurrency: + group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + steps: + - name: Resolve collection name + id: resolve + shell: bash + run: | + COLLECTION_ID="${{ inputs.oa-collection-id }}" + # Do NOT use -L: %{redirect_url} is only populated when curl does not follow the redirect. + DOWNLOAD_URL=$(curl -fsS \ + -H "Authorization: Bearer ${OA_API_TOKEN}" \ + -w "%{redirect_url}" -o /dev/null \ + "https://batch.openaddresses.io/api/collections/${COLLECTION_ID}/data") + if [ -z "${DOWNLOAD_URL}" ]; then + echo "ERROR: could not resolve download URL for collection ${COLLECTION_ID}" >&2 + exit 1 + fi + # Extract name from URL: https://.../collection-ca.zip -> ca + COLLECTION_NAME=$(basename "${DOWNLOAD_URL}" | sed 's/^collection-//;s/\.zip$//') + echo "Collection ${COLLECTION_ID} -> name: ${COLLECTION_NAME}, url: ${DOWNLOAD_URL}" + echo "collection-name=${COLLECTION_NAME}" >> "$GITHUB_OUTPUT" + echo "download-url=${DOWNLOAD_URL}" >> "$GITHUB_OUTPUT" + + - name: Download OpenAddresses collection + shell: bash + run: | + COLLECTION_NAME="${{ steps.resolve.outputs.collection-name }}" + DOWNLOAD_URL="${{ steps.resolve.outputs.download-url }}" + DEST="/home/planet/collection-oa-${COLLECTION_NAME}.zip" + + echo "Downloading collection ${COLLECTION_NAME} to ${DEST} ..." + [ -f "${DEST}" ] && mv -f "${DEST}" "${DEST}.bak" + curl -fsSL -o "${DEST}" "${DOWNLOAD_URL}" + echo "Downloaded $(du -sh "${DEST}" | cut -f1) to ${DEST}" + + curl -X POST https://comaps.zulipchat.com/api/v1/messages \ + -u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \ + --data-urlencode type=stream \ + --data-urlencode 'to="DevOps"' \ + --data-urlencode topic=codeberg-bot \ + --data-urlencode "content=OpenAddresses collection ${COLLECTION_NAME} downloaded." + + - name: Checkout main repo + shell: bash + run: | + echo "Cloning $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY branch $FORGEJO_REF_NAME" + cd ~ + git clone --depth 1 --recurse-submodules --shallow-submodules \ + -b $FORGEJO_REF_NAME --single-branch \ + $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps + + - name: Install Python dependencies + shell: bash + # shapely was added to requirements.txt in this PR but the pinned container + # image predates it. Install at runtime until the image is rebuilt. + # TODO: remove this step once maps_generator image is rebuilt with new requirements.txt + run: | + pip install --quiet "shapely>=2.0" + + - name: Run OpenAddresses preprocessor + shell: bash + run: | + COLLECTION_NAME="${{ steps.resolve.outputs.collection-name }}" + ZIP="/home/planet/collection-oa-${COLLECTION_NAME}.zip" + OUTPUT_DIR="/home/planet/oa-out-${COLLECTION_NAME}" + BORDERS_DIR="${HOME}/comaps/data/borders" + + [ -f "${ZIP}" ] || { echo "ERROR: ${ZIP} not found — re-run the workflow to download it" >&2; exit 1; } + + echo "Backing up previous output ..." + rm -rf "${OUTPUT_DIR}.bak" + [ -d "${OUTPUT_DIR}" ] && mv -fT "${OUTPUT_DIR}" "${OUTPUT_DIR}.bak" || true + mkdir -p "${OUTPUT_DIR}" + + echo "Running preprocessor ..." + python3 ~/comaps/tools/python/maps_generator/generator/openaddresses_preprocessor.py \ + "${ZIP}" \ + "${OUTPUT_DIR}" \ + --borders-dir "${BORDERS_DIR}" + + echo "Preprocessor output:" + ls -lah "${OUTPUT_DIR}" | head -20 + echo "DONE" + + curl -X POST https://comaps.zulipchat.com/api/v1/messages \ + -u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \ + --data-urlencode type=stream \ + --data-urlencode 'to="DevOps"' \ + --data-urlencode topic=codeberg-bot \ + --data-urlencode "content=OpenAddresses preprocessor finished for collection ${COLLECTION_NAME}. Output at ${OUTPUT_DIR}." diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 06ec4aa4c..7f4a9e1fa 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -16,6 +16,7 @@ Gonzalo Pesquero Harry Bond Konstantin Pastbin @pastk Leonardo Bishop +lone-cloud Marko Kocic Matheus Gomes @NoelClick diff --git a/android/app/src/main/java/app/organicmaps/widget/placepage/PlacePageView.java b/android/app/src/main/java/app/organicmaps/widget/placepage/PlacePageView.java index 6aa323676..24403f430 100644 --- a/android/app/src/main/java/app/organicmaps/widget/placepage/PlacePageView.java +++ b/android/app/src/main/java/app/organicmaps/widget/placepage/PlacePageView.java @@ -145,6 +145,10 @@ public class PlacePageView extends Fragment private MaterialTextView mTvCharge; private View mWheelchair; private MaterialTextView mTvWheelchair; + private View mCapacityDisabled; + private MaterialTextView mTvCapacityDisabled; + private View mCapacityCharging; + private MaterialTextView mTvCapacityCharging; private View mDriveThrough; private MaterialTextView mTvDriveThrough; private View mSelfService; @@ -326,6 +330,10 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat mTvCharge = mFrame.findViewById(R.id.tv__place_charge); mWheelchair = mFrame.findViewById(R.id.ll__place_wheelchair); mTvWheelchair = mFrame.findViewById(R.id.tv__place_wheelchair); + mCapacityDisabled = mFrame.findViewById(R.id.ll__place_capacity_disabled); + mTvCapacityDisabled = mFrame.findViewById(R.id.tv__place_capacity_disabled); + mCapacityCharging = mFrame.findViewById(R.id.ll__place_capacity_charging); + mTvCapacityCharging = mFrame.findViewById(R.id.tv__place_capacity_charging); mDriveThrough = mFrame.findViewById(R.id.ll__place_drive_through); mTvDriveThrough = mFrame.findViewById(R.id.tv__place_drive_through); mSelfService = mFrame.findViewById(R.id.ll__place_self_service); @@ -353,6 +361,8 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat mRooms.setOnLongClickListener(this); mCharge.setOnLongClickListener(this); mWheelchair.setOnLongClickListener(this); + mCapacityDisabled.setOnLongClickListener(this); + mCapacityCharging.setOnLongClickListener(this); mDriveThrough.setOnLongClickListener(this); mSelfService.setOnLongClickListener(this); mOutdoorSeating.setOnLongClickListener(this); @@ -706,6 +716,22 @@ private void refreshDetails() getLocalizedFeatureType(getContext(), mMapObject.getMetadata(Metadata.MetadataType.FMD_WHEELCHAIR)); refreshMetadataOrHide(wheelchair, mWheelchair, mTvWheelchair); + final String capacityDisabled = + getLocalizedFeatureType(getContext(), mMapObject.getMetadata(Metadata.MetadataType.FMD_CAPACITY_DISABLED)); + refreshMetadataOrHide(switch (capacityDisabled) { + case "yes" -> getString(R.string.capacity_disabled_yes); + case "no" -> getString(R.string.capacity_disabled_no); + default -> getString(R.string.capacity_disabled, capacityDisabled); + }, mCapacityDisabled, mTvCapacityDisabled); + + final String capacityCharging = + getLocalizedFeatureType(getContext(), mMapObject.getMetadata(Metadata.MetadataType.FMD_CAPACITY_CHARGING)); + refreshMetadataOrHide(switch (capacityCharging) { + case "yes" -> getString(R.string.capacity_disabled_yes); + case "no" -> getString(R.string.capacity_disabled_no); + default -> getString(R.string.capacity_disabled, capacityCharging); + }, mCapacityCharging, mTvCapacityCharging); + final String driveThrough = mMapObject.getMetadata(Metadata.MetadataType.FMD_DRIVE_THROUGH); refreshMetadataOrHide(driveThrough.equals("yes") ? getString(R.string.drive_through) : "", mDriveThrough, mTvDriveThrough); @@ -1121,6 +1147,10 @@ else if (id == R.id.ll__place_charge) items.add(mTvCharge.getText().toString()); else if (id == R.id.ll__place_wheelchair) items.add(mTvWheelchair.getText().toString()); + else if (id == R.id.ll__place_capacity_disabled) + items.add(mTvCapacityDisabled.getText().toString()); + else if (id == R.id.ll__place_capacity_charging) + items.add(mTvCapacityCharging.getText().toString()); else if (id == R.id.ll__place_drive_through) items.add(mTvDriveThrough.getText().toString()); else if (id == R.id.ll__place_outdoor_seating) diff --git a/android/app/src/main/res/layout/place_page_capacity_charging.xml b/android/app/src/main/res/layout/place_page_capacity_charging.xml new file mode 100644 index 000000000..38c1cb209 --- /dev/null +++ b/android/app/src/main/res/layout/place_page_capacity_charging.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/android/app/src/main/res/layout/place_page_capacity_disabled.xml b/android/app/src/main/res/layout/place_page_capacity_disabled.xml new file mode 100644 index 000000000..38a5f4e58 --- /dev/null +++ b/android/app/src/main/res/layout/place_page_capacity_disabled.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/android/app/src/main/res/layout/place_page_details.xml b/android/app/src/main/res/layout/place_page_details.xml index eb51ab345..901c945a7 100644 --- a/android/app/src/main/res/layout/place_page_details.xml +++ b/android/app/src/main/res/layout/place_page_details.xml @@ -64,6 +64,10 @@ + + + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 3f23b63ba..b82d07c19 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1019,6 +1019,7 @@ Not following route Recalculating the route… + Rebuilding route… Automatically open third-party links Open third-party links in CoMaps by default Keyboard incognito mode @@ -1028,4 +1029,10 @@ The app has not been installed from Google Play, you can\'t use it in your car. Press the setting to get more details on our FAQ. Recently Used + Number of disabled parking spaces: %s + Has disabled parking spaces + No disabled parking spaces + Spaces with chargers: %s + Has spaces reserved for electric vehicles + No spaces reserved for electric vehicles diff --git a/android/sdk/src/main/java/app/organicmaps/sdk/bookmarks/data/Metadata.java b/android/sdk/src/main/java/app/organicmaps/sdk/bookmarks/data/Metadata.java index bf0234428..c8d36cb15 100644 --- a/android/sdk/src/main/java/app/organicmaps/sdk/bookmarks/data/Metadata.java +++ b/android/sdk/src/main/java/app/organicmaps/sdk/bookmarks/data/Metadata.java @@ -76,7 +76,9 @@ public enum MetadataType FMD_CHARGE_SOCKETS(56), FMD_ROOMS(57), FMD_CHARGE(58), - FMD_POPULATION(59); + FMD_POPULATION(59), + FMD_CAPACITY_DISABLED(60), + FMD_CAPACITY_CHARGING(61); private final int mMetaType; MetadataType(int metadataType) @@ -85,7 +87,7 @@ public enum MetadataType } @NonNull - public static MetadataType fromInt(@IntRange(from = 1, to = 59) int metaType) + public static MetadataType fromInt(@IntRange(from = 1, to = 61) int metaType) { for (MetadataType type : values()) if (type.mMetaType == metaType) diff --git a/android/sdk/src/main/res/values-af/types_strings.xml b/android/sdk/src/main/res/values-af/types_strings.xml index 7a5cf0ee5..4cc8bfa49 100644 --- a/android/sdk/src/main/res/values-af/types_strings.xml +++ b/android/sdk/src/main/res/values-af/types_strings.xml @@ -359,7 +359,24 @@ Tonnel Bushalte + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou + Pad in aanbou Fietspad Brug diff --git a/android/sdk/src/main/res/values-ar/types_strings.xml b/android/sdk/src/main/res/values-ar/types_strings.xml index 10edd1006..536a3f089 100644 --- a/android/sdk/src/main/res/values-ar/types_strings.xml +++ b/android/sdk/src/main/res/values-ar/types_strings.xml @@ -380,7 +380,24 @@ نفق موقف حافلات + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء + طريق تحت الإنشاء مسار للدراجات جسر diff --git a/android/sdk/src/main/res/values-az/types_strings.xml b/android/sdk/src/main/res/values-az/types_strings.xml index fd4f9fed8..775844b63 100644 --- a/android/sdk/src/main/res/values-az/types_strings.xml +++ b/android/sdk/src/main/res/values-az/types_strings.xml @@ -370,7 +370,24 @@ Tunel Avtobus dayanacağı + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol + Tikili Yol Velosiped yolu Körpü diff --git a/android/sdk/src/main/res/values-bg/types_strings.xml b/android/sdk/src/main/res/values-bg/types_strings.xml index 06fc1e3ed..da11056df 100644 --- a/android/sdk/src/main/res/values-bg/types_strings.xml +++ b/android/sdk/src/main/res/values-bg/types_strings.xml @@ -956,7 +956,24 @@ Виетнамска Пътека за юздечки Пътека за юздечки + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане + Път в процес на изграждане Жилищна улица Пътека Пътека diff --git a/android/sdk/src/main/res/values-ca/types_strings.xml b/android/sdk/src/main/res/values-ca/types_strings.xml index 0a4e997b9..6df496e75 100644 --- a/android/sdk/src/main/res/values-ca/types_strings.xml +++ b/android/sdk/src/main/res/values-ca/types_strings.xml @@ -935,7 +935,24 @@ Centre comercial Desfibril·lador Carretera + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció + Via en construcció Continent Quiosc diff --git a/android/sdk/src/main/res/values-cs/types_strings.xml b/android/sdk/src/main/res/values-cs/types_strings.xml index d91b9835d..52dc70d58 100644 --- a/android/sdk/src/main/res/values-cs/types_strings.xml +++ b/android/sdk/src/main/res/values-cs/types_strings.xml @@ -327,7 +327,24 @@ Tunel Autobusová zastávka + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci + Silnice v rekonstrukci Most diff --git a/android/sdk/src/main/res/values-da/types_strings.xml b/android/sdk/src/main/res/values-da/types_strings.xml index dbe7a04fe..f4d7e6e72 100644 --- a/android/sdk/src/main/res/values-da/types_strings.xml +++ b/android/sdk/src/main/res/values-da/types_strings.xml @@ -317,7 +317,24 @@ Tunnel Busstoppested + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse + Vej under anlæggelse Bro diff --git a/android/sdk/src/main/res/values-de/types_strings.xml b/android/sdk/src/main/res/values-de/types_strings.xml index 4893a5e81..e63974097 100644 --- a/android/sdk/src/main/res/values-de/types_strings.xml +++ b/android/sdk/src/main/res/values-de/types_strings.xml @@ -417,7 +417,24 @@ Tunnel Bushaltestelle + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau + Straße im Bau Radweg Brücke diff --git a/android/sdk/src/main/res/values-el/types_strings.xml b/android/sdk/src/main/res/values-el/types_strings.xml index 45f47f764..353073ae1 100644 --- a/android/sdk/src/main/res/values-el/types_strings.xml +++ b/android/sdk/src/main/res/values-el/types_strings.xml @@ -335,7 +335,24 @@ Σήραγγα Στάση λεωφορείου + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή + Οδός υπό κατασκευή Γέφυρα diff --git a/android/sdk/src/main/res/values-es-rMX/types_strings.xml b/android/sdk/src/main/res/values-es-rMX/types_strings.xml index fb4916e55..ef0f8710d 100644 --- a/android/sdk/src/main/res/values-es-rMX/types_strings.xml +++ b/android/sdk/src/main/res/values-es-rMX/types_strings.xml @@ -57,7 +57,24 @@ Puente Túnel + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción Puente diff --git a/android/sdk/src/main/res/values-es/types_strings.xml b/android/sdk/src/main/res/values-es/types_strings.xml index 5491fb38e..d77cdc2d2 100644 --- a/android/sdk/src/main/res/values-es/types_strings.xml +++ b/android/sdk/src/main/res/values-es/types_strings.xml @@ -385,7 +385,24 @@ Túnel Parada de bus + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción + Vía en construcción Ciclovía Puente diff --git a/android/sdk/src/main/res/values-et/types_strings.xml b/android/sdk/src/main/res/values-et/types_strings.xml index e34b63e97..cc220cd8e 100644 --- a/android/sdk/src/main/res/values-et/types_strings.xml +++ b/android/sdk/src/main/res/values-et/types_strings.xml @@ -382,7 +382,24 @@ Tunnel Bussipeatus + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee + Ehitusjärgus tee Jalgrattatee Jalgrattasild diff --git a/android/sdk/src/main/res/values-eu/types_strings.xml b/android/sdk/src/main/res/values-eu/types_strings.xml index 26a512e4c..324e6480c 100644 --- a/android/sdk/src/main/res/values-eu/types_strings.xml +++ b/android/sdk/src/main/res/values-eu/types_strings.xml @@ -373,7 +373,24 @@ Tunela Autobus geltokia + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea + Eraikitzen ari diren errepidea Bidegorri edo bizikleta-bidea Zubia diff --git a/android/sdk/src/main/res/values-fa/types_strings.xml b/android/sdk/src/main/res/values-fa/types_strings.xml index 5ff2035ee..656cf590e 100644 --- a/android/sdk/src/main/res/values-fa/types_strings.xml +++ b/android/sdk/src/main/res/values-fa/types_strings.xml @@ -244,7 +244,24 @@ تونل حمل و نقل + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است + جاده در دست ساخت است پل diff --git a/android/sdk/src/main/res/values-fi/types_strings.xml b/android/sdk/src/main/res/values-fi/types_strings.xml index e0fa7245b..eb775e21d 100644 --- a/android/sdk/src/main/res/values-fi/types_strings.xml +++ b/android/sdk/src/main/res/values-fi/types_strings.xml @@ -375,7 +375,24 @@ Tunneli Bussipysäkki + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie + Rakenteilla oleva tie Pyörätie Silta diff --git a/android/sdk/src/main/res/values-fr/types_strings.xml b/android/sdk/src/main/res/values-fr/types_strings.xml index 7bec9fb23..06570a226 100644 --- a/android/sdk/src/main/res/values-fr/types_strings.xml +++ b/android/sdk/src/main/res/values-fr/types_strings.xml @@ -370,7 +370,24 @@ Tunnel Arrêt de bus + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction + Route en construction Piste cyclable Pont @@ -1390,6 +1407,7 @@ Poste de garde forestier Escape room Abri pour animaux + Scène Portillon Bureau des agents de sécurité Guérite de sécurité diff --git a/android/sdk/src/main/res/values-gl/types_strings.xml b/android/sdk/src/main/res/values-gl/types_strings.xml index a07fca348..7bed81337 100644 --- a/android/sdk/src/main/res/values-gl/types_strings.xml +++ b/android/sdk/src/main/res/values-gl/types_strings.xml @@ -367,7 +367,24 @@ Puente Túnel Parada de autobús + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción + Vía en construción Ciclovía Puente Ciclovía diff --git a/android/sdk/src/main/res/values-gsw/types_strings.xml b/android/sdk/src/main/res/values-gsw/types_strings.xml index 3ea62239b..04c5a508d 100644 --- a/android/sdk/src/main/res/values-gsw/types_strings.xml +++ b/android/sdk/src/main/res/values-gsw/types_strings.xml @@ -333,7 +333,24 @@ Brugg Tunnel Bushaltistell + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau + Strass im Bau Veloweg Brugg Veloweg diff --git a/android/sdk/src/main/res/values-hi/types_strings.xml b/android/sdk/src/main/res/values-hi/types_strings.xml index 9cc4513fd..055d40fe6 100644 --- a/android/sdk/src/main/res/values-hi/types_strings.xml +++ b/android/sdk/src/main/res/values-hi/types_strings.xml @@ -263,7 +263,24 @@ राजमार्ग बस स्टॉप + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क + निर्माणाधीन सड़क साइकिल मार्ग साइकिल मार्ग उत्थापक diff --git a/android/sdk/src/main/res/values-hu/types_strings.xml b/android/sdk/src/main/res/values-hu/types_strings.xml index 74d6596c7..82364be31 100644 --- a/android/sdk/src/main/res/values-hu/types_strings.xml +++ b/android/sdk/src/main/res/values-hu/types_strings.xml @@ -329,7 +329,24 @@ Alagút Buszmegálló + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés + Útépítés Híd diff --git a/android/sdk/src/main/res/values-in/types_strings.xml b/android/sdk/src/main/res/values-in/types_strings.xml index 81ffcc586..7490e05e7 100644 --- a/android/sdk/src/main/res/values-in/types_strings.xml +++ b/android/sdk/src/main/res/values-in/types_strings.xml @@ -323,7 +323,24 @@ Terowongan Halte bus + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun + Jalan sedang dibangun Menjembatani diff --git a/android/sdk/src/main/res/values-is/types_strings.xml b/android/sdk/src/main/res/values-is/types_strings.xml index 0ce70b142..40860f438 100644 --- a/android/sdk/src/main/res/values-is/types_strings.xml +++ b/android/sdk/src/main/res/values-is/types_strings.xml @@ -1046,7 +1046,24 @@ Snjóleikjagarður Þráðlaust net Setskýli + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu + Vegur í byggingu Svæði fyrir fótgangandi Svæði fyrir fótgangandi Sögulegur skriðdreki diff --git a/android/sdk/src/main/res/values-it/types_strings.xml b/android/sdk/src/main/res/values-it/types_strings.xml index 1bb8eefaa..d60ebf42e 100644 --- a/android/sdk/src/main/res/values-it/types_strings.xml +++ b/android/sdk/src/main/res/values-it/types_strings.xml @@ -382,7 +382,24 @@ Galleria Fermata dell\'autobus + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione + Strada in costruzione Pista ciclabile Ponte diff --git a/android/sdk/src/main/res/values-iw/types_strings.xml b/android/sdk/src/main/res/values-iw/types_strings.xml index f52b636fe..0c19d9a4f 100644 --- a/android/sdk/src/main/res/values-iw/types_strings.xml +++ b/android/sdk/src/main/res/values-iw/types_strings.xml @@ -382,7 +382,24 @@ מִנהָרָה תחנת אוטובוס + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה + כביש בבניה שביל אופניים גשר לאופניים diff --git a/android/sdk/src/main/res/values-ja/types_strings.xml b/android/sdk/src/main/res/values-ja/types_strings.xml index 87d7c51b5..1176beea6 100644 --- a/android/sdk/src/main/res/values-ja/types_strings.xml +++ b/android/sdk/src/main/res/values-ja/types_strings.xml @@ -356,7 +356,24 @@ トンネル バス停 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 + 工事中の道路 自転車道 自転車道(橋) diff --git a/android/sdk/src/main/res/values-ko/types_strings.xml b/android/sdk/src/main/res/values-ko/types_strings.xml index e62739e1a..9d1c1912d 100644 --- a/android/sdk/src/main/res/values-ko/types_strings.xml +++ b/android/sdk/src/main/res/values-ko/types_strings.xml @@ -330,7 +330,24 @@ 터널 버스 정류장 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 + 공사 중 도로 다리 diff --git a/android/sdk/src/main/res/values-kw/types_strings.xml b/android/sdk/src/main/res/values-kw/types_strings.xml index 8d8b9cb22..326064c6b 100644 --- a/android/sdk/src/main/res/values-kw/types_strings.xml +++ b/android/sdk/src/main/res/values-kw/types_strings.xml @@ -286,7 +286,24 @@ Pons Kowfordh Kyttrinva + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans + Fordh y\'n Drehevyans Hyns rag Diwrosow Pons Hyns rag Diwrosow diff --git a/android/sdk/src/main/res/values-lt/types_strings.xml b/android/sdk/src/main/res/values-lt/types_strings.xml index 1b44e94f8..5f73fdd1b 100644 --- a/android/sdk/src/main/res/values-lt/types_strings.xml +++ b/android/sdk/src/main/res/values-lt/types_strings.xml @@ -466,7 +466,24 @@ Tiltas Tunelis Stotelė + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias + Tiesiamas kelias Dviračių takas Tiltas Dviračių takas diff --git a/android/sdk/src/main/res/values-mr/types_strings.xml b/android/sdk/src/main/res/values-mr/types_strings.xml index b8628957d..967171b06 100644 --- a/android/sdk/src/main/res/values-mr/types_strings.xml +++ b/android/sdk/src/main/res/values-mr/types_strings.xml @@ -290,7 +290,24 @@ बोगदा बस थांबा + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता + बांधकामाधीन रस्ता सायकल वाट पूल diff --git a/android/sdk/src/main/res/values-nb/types_strings.xml b/android/sdk/src/main/res/values-nb/types_strings.xml index c3b4a5905..36fdb7d5b 100644 --- a/android/sdk/src/main/res/values-nb/types_strings.xml +++ b/android/sdk/src/main/res/values-nb/types_strings.xml @@ -337,7 +337,24 @@ Tunnel Busstopp + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon + Veikonstruksjon Sykkelvei Bru diff --git a/android/sdk/src/main/res/values-nl/types_strings.xml b/android/sdk/src/main/res/values-nl/types_strings.xml index a11876861..801130ef4 100644 --- a/android/sdk/src/main/res/values-nl/types_strings.xml +++ b/android/sdk/src/main/res/values-nl/types_strings.xml @@ -379,7 +379,24 @@ Tunnel Bushalte + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw + Weg in aanbouw Fietspad Fietsbrug diff --git a/android/sdk/src/main/res/values-pl/types_strings.xml b/android/sdk/src/main/res/values-pl/types_strings.xml index d7902953e..fc7f7116d 100644 --- a/android/sdk/src/main/res/values-pl/types_strings.xml +++ b/android/sdk/src/main/res/values-pl/types_strings.xml @@ -380,7 +380,24 @@ Tunel Przystanek autobusowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy + Droga w trakcie budowy Droga rowerowa Most drogowy dla rowerów diff --git a/android/sdk/src/main/res/values-pt-rBR/types_strings.xml b/android/sdk/src/main/res/values-pt-rBR/types_strings.xml index afaba647a..d187e3702 100644 --- a/android/sdk/src/main/res/values-pt-rBR/types_strings.xml +++ b/android/sdk/src/main/res/values-pt-rBR/types_strings.xml @@ -333,7 +333,24 @@ Túnel Ponto de ônibus + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção + Via em construção Ciclovia Ponte para ciclistas diff --git a/android/sdk/src/main/res/values-pt/types_strings.xml b/android/sdk/src/main/res/values-pt/types_strings.xml index 1895275b5..d3452a50a 100644 --- a/android/sdk/src/main/res/values-pt/types_strings.xml +++ b/android/sdk/src/main/res/values-pt/types_strings.xml @@ -368,7 +368,24 @@ Túnel Paragem de autocarros + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção + Estrada em construção Ciclovia Ponte diff --git a/android/sdk/src/main/res/values-ro/types_strings.xml b/android/sdk/src/main/res/values-ro/types_strings.xml index 8cce5160e..a566ed311 100644 --- a/android/sdk/src/main/res/values-ro/types_strings.xml +++ b/android/sdk/src/main/res/values-ro/types_strings.xml @@ -322,7 +322,24 @@ Tunel Stație de autobuz + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție + Drum în construcție Pod diff --git a/android/sdk/src/main/res/values-ru/types_strings.xml b/android/sdk/src/main/res/values-ru/types_strings.xml index a498d2f31..b9f104442 100644 --- a/android/sdk/src/main/res/values-ru/types_strings.xml +++ b/android/sdk/src/main/res/values-ru/types_strings.xml @@ -386,7 +386,24 @@ Тоннель Остановка + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога + Строящаяся дорога Велодорожка Мост diff --git a/android/sdk/src/main/res/values-sk/types_strings.xml b/android/sdk/src/main/res/values-sk/types_strings.xml index c20f3af01..3fe46e90f 100644 --- a/android/sdk/src/main/res/values-sk/types_strings.xml +++ b/android/sdk/src/main/res/values-sk/types_strings.xml @@ -374,7 +374,24 @@ Tunel Autobusová zastávka + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe + Cesta vo výstavbe Cyklocesta Most diff --git a/android/sdk/src/main/res/values-sl/types_strings.xml b/android/sdk/src/main/res/values-sl/types_strings.xml index 0ab7d669b..02d2f9bde 100644 --- a/android/sdk/src/main/res/values-sl/types_strings.xml +++ b/android/sdk/src/main/res/values-sl/types_strings.xml @@ -498,7 +498,24 @@ Most Predor Avtobusno postajališče + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji + Cesta v gradnji Kolesarska steza Most Kolesarska steza diff --git a/android/sdk/src/main/res/values-sr/types_strings.xml b/android/sdk/src/main/res/values-sr/types_strings.xml index e4badaa1a..156b99187 100644 --- a/android/sdk/src/main/res/values-sr/types_strings.xml +++ b/android/sdk/src/main/res/values-sr/types_strings.xml @@ -383,7 +383,24 @@ Тунел Аутобуско стајалиште + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи + Пут у изградњи Бициклистичка стаза Мост diff --git a/android/sdk/src/main/res/values-sv/types_strings.xml b/android/sdk/src/main/res/values-sv/types_strings.xml index 3e1aa59d5..7ba2636d8 100644 --- a/android/sdk/src/main/res/values-sv/types_strings.xml +++ b/android/sdk/src/main/res/values-sv/types_strings.xml @@ -325,7 +325,24 @@ Tunnel Busshållplats + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande + Väg under uppförande Cykelbro diff --git a/android/sdk/src/main/res/values-sw/types_strings.xml b/android/sdk/src/main/res/values-sw/types_strings.xml index d8e1e523d..95b44a2ce 100644 --- a/android/sdk/src/main/res/values-sw/types_strings.xml +++ b/android/sdk/src/main/res/values-sw/types_strings.xml @@ -131,7 +131,24 @@ Daraja Mtaro + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa + Barabara inatengenezwa Daraja diff --git a/android/sdk/src/main/res/values-ta/types_strings.xml b/android/sdk/src/main/res/values-ta/types_strings.xml index 8ed26f4f7..65414639a 100644 --- a/android/sdk/src/main/res/values-ta/types_strings.xml +++ b/android/sdk/src/main/res/values-ta/types_strings.xml @@ -386,7 +386,24 @@ பாலம் சுரங்கப்பாதை பேருந்து நிறுத்தம் + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது + சாலை கட்டுமானத்தில் உள்ளது சைக்கிள் பாதை பாலம் சைக்கிள் பாதை diff --git a/android/sdk/src/main/res/values-th/types_strings.xml b/android/sdk/src/main/res/values-th/types_strings.xml index 202ca4b7a..5291511e8 100644 --- a/android/sdk/src/main/res/values-th/types_strings.xml +++ b/android/sdk/src/main/res/values-th/types_strings.xml @@ -331,7 +331,24 @@ อุโมงค์ ป้ายรถเมล์ + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง + ทางกำลังอยู่ในการก่อสร้าง สะพาน diff --git a/android/sdk/src/main/res/values-tr/types_strings.xml b/android/sdk/src/main/res/values-tr/types_strings.xml index f70ecdc6e..386bb6673 100644 --- a/android/sdk/src/main/res/values-tr/types_strings.xml +++ b/android/sdk/src/main/res/values-tr/types_strings.xml @@ -376,7 +376,24 @@ Tünel Otobüs Durağı + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol + Yapım Aşamasında Yol Bisiklet Yolu Köprü diff --git a/android/sdk/src/main/res/values-uk/types_strings.xml b/android/sdk/src/main/res/values-uk/types_strings.xml index e380e0325..4df751ab0 100644 --- a/android/sdk/src/main/res/values-uk/types_strings.xml +++ b/android/sdk/src/main/res/values-uk/types_strings.xml @@ -381,7 +381,24 @@ Тунель Зупинка + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується + Дорога, що будується Велодоріжка Міст diff --git a/android/sdk/src/main/res/values-vi/types_strings.xml b/android/sdk/src/main/res/values-vi/types_strings.xml index 8b290ad6a..4f2668991 100644 --- a/android/sdk/src/main/res/values-vi/types_strings.xml +++ b/android/sdk/src/main/res/values-vi/types_strings.xml @@ -329,7 +329,24 @@ Đường hầm Bến xe buýt + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công + Đường đang thi công Cầu diff --git a/android/sdk/src/main/res/values-zh-rHK/types_strings.xml b/android/sdk/src/main/res/values-zh-rHK/types_strings.xml index ece4baf03..2f0dc49e2 100644 --- a/android/sdk/src/main/res/values-zh-rHK/types_strings.xml +++ b/android/sdk/src/main/res/values-zh-rHK/types_strings.xml @@ -379,7 +379,24 @@ 隧道 巴士站 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 自行車道 diff --git a/android/sdk/src/main/res/values-zh-rTW/types_strings.xml b/android/sdk/src/main/res/values-zh-rTW/types_strings.xml index 73032d099..1d996d812 100644 --- a/android/sdk/src/main/res/values-zh-rTW/types_strings.xml +++ b/android/sdk/src/main/res/values-zh-rTW/types_strings.xml @@ -626,7 +626,24 @@ 橋樑 隧道 公車站 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 + 施工中道路 單車道 橋樑 單車道 diff --git a/android/sdk/src/main/res/values-zh/types_strings.xml b/android/sdk/src/main/res/values-zh/types_strings.xml index da409ba11..b5afc1da0 100644 --- a/android/sdk/src/main/res/values-zh/types_strings.xml +++ b/android/sdk/src/main/res/values-zh/types_strings.xml @@ -380,7 +380,24 @@ 隧道 公交站 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 + 在建道路 自行车道 diff --git a/android/sdk/src/main/res/values/types_strings.xml b/android/sdk/src/main/res/values/types_strings.xml index feb7aedc5..b824ce48e 100644 --- a/android/sdk/src/main/res/values/types_strings.xml +++ b/android/sdk/src/main/res/values/types_strings.xml @@ -212,6 +212,7 @@ Waste Transfer Station Water Tank Refill Point Water Tank Refill Point + Stage Barrier Barrier Block @@ -456,7 +457,24 @@ Tunnel Bus Stop + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction + Road Under Construction Cycle Path Bridge diff --git a/data/categories-strings/en.json/localize.json b/data/categories-strings/en.json/localize.json index 848c65ee0..5498c03d8 100644 --- a/data/categories-strings/en.json/localize.json +++ b/data/categories-strings/en.json/localize.json @@ -512,6 +512,7 @@ "shop-wholesale|@shop": "Wholesale", "leisure-track": "Track", "leisure-bandstand": "5Bandstand", +"amenity-stage": "Stage", "power-plant": "Power Plant", "power-generator-wind": "Wind Generator", "shop-auction|@category_secondhand": "4Auction|Auctioneer|Auction House", diff --git a/data/conf/isolines/countries-to-generate.json b/data/conf/isolines/countries-to-generate.json index 5346c4633..a22755ae7 100644 --- a/data/conf/isolines/countries-to-generate.json +++ b/data/conf/isolines/countries-to-generate.json @@ -2852,7 +2852,7 @@ { "key": "France_Rhone-Alpes_Ain", "value": { - "profileName": "high", + "profileName": "high10", "tileCoordsSubset": [], "tilesAreBanned": false } @@ -2860,7 +2860,7 @@ { "key": "France_Rhone-Alpes_Ardeche", "value": { - "profileName": "high", + "profileName": "high10", "tileCoordsSubset": [], "tilesAreBanned": false } @@ -2868,7 +2868,7 @@ { "key": "France_Rhone-Alpes_Drome", "value": { - "profileName": "high", + "profileName": "high10", "tileCoordsSubset": [], "tilesAreBanned": false } @@ -2876,7 +2876,7 @@ { "key": "France_Rhone-Alpes_Haute-Savoie", "value": { - "profileName": "high", + "profileName": "high10", "tileCoordsSubset": [], "tilesAreBanned": false } @@ -2884,7 +2884,7 @@ { "key": "France_Rhone-Alpes_Isere", "value": { - "profileName": "high", + "profileName": "high10", "tileCoordsSubset": [], "tilesAreBanned": false } @@ -2892,7 +2892,7 @@ { "key": "France_Rhone-Alpes_Loire", "value": { - "profileName": "high", + "profileName": "high10", "tileCoordsSubset": [], "tilesAreBanned": false } @@ -2900,7 +2900,7 @@ { "key": "France_Rhone-Alpes_Rhone", "value": { - "profileName": "high", + "profileName": "high10", "tileCoordsSubset": [], "tilesAreBanned": false } @@ -2908,7 +2908,7 @@ { "key": "France_Rhone-Alpes_Savoie", "value": { - "profileName": "high_f2", + "profileName": "high10", "tileCoordsSubset": [], "tilesAreBanned": false } @@ -9949,4 +9949,4 @@ } } ] -} \ No newline at end of file +} diff --git a/data/conf/isolines/isolines-profiles.json b/data/conf/isolines/isolines-profiles.json index c9eb4eacf..d3de4457a 100644 --- a/data/conf/isolines/isolines-profiles.json +++ b/data/conf/isolines/isolines-profiles.json @@ -1,5 +1,17 @@ { "profiles": [ + { + "key": "high10", + "value": { + "alitudesStep": 10, + "gaussianFilterRFactor": 1.0, + "gaussianFilterStDev": 2.0, + "latLonStepFactor": 1, + "maxIsolinesLength": 500, + "medianFilterR": 1, + "simplificationZoom": 17 + } + }, { "key": "high", "value": { diff --git a/data/copyright.html b/data/copyright.html index aa691f520..e58494b10 100644 --- a/data/copyright.html +++ b/data/copyright.html @@ -96,6 +96,7 @@

Map data © OpenStreetMap contributors, ODbL.

+

Address data in some regions © OpenAddresses contributors.

Картографические данные © участники OpenStreetMap, ODbL.

Dữ liệu bản đồ © Cộng tác viên của OpenStreetMap, ODbL.

Harita verileri © OpenStreetMap katkıları, ODbL.

diff --git a/data/editor.config b/data/editor.config index d9a423064..18eb2f484 100644 --- a/data/editor.config +++ b/data/editor.config @@ -521,6 +521,9 @@ + + + diff --git a/data/mapcss-mapping.csv b/data/mapcss-mapping.csv index 2b5a43e86..5afbc6b8e 100644 --- a/data/mapcss-mapping.csv +++ b/data/mapcss-mapping.csv @@ -340,7 +340,7 @@ waterway|drain|tunnel;[waterway=drain][tunnel?];;name;int_name;230; landuse|cemetery|christian;[landuse=cemetery][religion=christian];;name;int_name;231; highway|cycleway|tunnel;[highway=cycleway][tunnel?];;name;int_name;232; amenity|parking|permissive;[amenity=parking][access=permissive];;name;int_name;233; -deprecated:boundary|administrative|5:04.2024;[boundary=administrative][admin_level=5];x;name;int_name;234; +amenity|stage;234; highway|unclassified|tunnel;[highway=unclassified][tunnel?];;name;int_name;235; amenity|recycling|centre;[amenity=recycling][recycling_type=centre];;name;int_name;236; deprecated:amenity|recycling:01.2026;237;amenity|recycling|container @@ -916,22 +916,22 @@ leisure|sports_centre|sport|soccer;[leisure=sports_centre][sport=soccer];;name;i leisure|sports_centre|sport|four_square;[leisure=sports_centre][sport=four_square];;name;int_name;787; leisure|sports_centre|sport|boules;[leisure=sports_centre][sport=boules];;name;int_name;788; leisure|sports_centre|sport|pickleball;[leisure=sports_centre][sport=pickleball];;name;int_name;789; -deprecated|deprecated;790;x -deprecated|deprecated;791;x -deprecated|deprecated;792;x -deprecated|deprecated;793;x -deprecated|deprecated;794;x -deprecated|deprecated;795;x -deprecated|deprecated;796;x -deprecated|deprecated;797;x -deprecated|deprecated;798;x -deprecated|deprecated;799;x -deprecated|deprecated;800;x -deprecated|deprecated;801;x -deprecated|deprecated;802;x -deprecated|deprecated;803;x -deprecated|deprecated;804;x -deprecated|deprecated;805;x +highway|construction|motorway;[highway=construction][construction=motorway];;name;int_name;790; +highway|construction|motorway_link;[highway=construction][construction=motorway_link];;name;int_name;791; +highway|construction|trunk;[highway=construction][construction=trunk];;name;int_name;792; +highway|construction|trunk_link;[highway=construction][construction=trunk_link];;name;int_name;793; +highway|construction|primary;[highway=construction][construction=primary];;name;int_name;794; +highway|construction|primary_link;[highway=construction][construction=primary_link];;name;int_name;795; +highway|construction|secondary;[highway=construction][construction=secondary];;name;int_name;796; +highway|construction|secondary_link;[highway=construction][construction=secondary_link];;name;int_name;797; +highway|construction|tertiary;[highway=construction][construction=tertiary];;name;int_name;798; +highway|construction|tertiary_link;[highway=construction][construction=tertiary_link];;name;int_name;799; +highway|construction|residential;[highway=construction][construction=residential];;name;int_name;800; +highway|construction|unclassified;[highway=construction][construction=unclassified];;name;int_name;801; +highway|construction|service;[highway=construction][construction=service];;name;int_name;802; +highway|construction|living_street;[highway=construction][construction=living_street];;name;int_name;803; +highway|construction|road;[highway=construction][construction=road];;name;int_name;804; +highway|construction|track;[highway=construction][construction=track];;name;int_name;805; deprecated|deprecated;806;x deprecated|deprecated;807;x deprecated|deprecated;808;x @@ -1759,4 +1759,4 @@ leisure|escape_game;1628; amenity|luggage_locker;1629; building|guardhouse;[building=guardhouse],[amenity=security_booth],[amenity=checkpoint];;;;1630; office|security;1631; -shop|lighting;1632; +shop|lighting;1632; \ No newline at end of file diff --git a/data/styles/default/dark/symbols/stage-m.svg b/data/styles/default/dark/symbols/stage-m.svg new file mode 100644 index 000000000..d29a3c427 --- /dev/null +++ b/data/styles/default/dark/symbols/stage-m.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/data/styles/default/include/Basemap.mapcss b/data/styles/default/include/Basemap.mapcss index 267ae714f..bee4e10a7 100644 --- a/data/styles/default/include/Basemap.mapcss +++ b/data/styles/default/include/Basemap.mapcss @@ -564,6 +564,7 @@ area|z15-[amenity=charging_station][motorcar?], area|z16-[amenity=charging_station], area|z15-[amenity=motorcycle_parking], area|z15-[amenity=bicycle_parking], +area|z17-[amenity=stage], {fill-opacity: 1; fill-color: @general_area;} diff --git a/data/styles/default/include/Icons.mapcss b/data/styles/default/include/Icons.mapcss index 0a1fea9a0..2bfbdea7d 100644 --- a/data/styles/default/include/Icons.mapcss +++ b/data/styles/default/include/Icons.mapcss @@ -1020,6 +1020,7 @@ node|z17-[amenity=social_facility], node|z17-[social_facility=food_bank], node|z17-[social_facility=soup_kitchen], node|z17-[amenity=animal_shelter], +node|z17-[amenity=stage], node|z17-[amenity=kindergarten], node|z17-[amenity=childcare], node|z16-[amenity=school], @@ -1222,6 +1223,11 @@ node|z17-[amenity=animal_shelter], node|z18-[amenity=animal_shelter], {font-size: 11;} +node|z17-[amenity=stage], +{icon-image: stage-m.svg;} +node|z18-[amenity=stage], +{font-size: 11;} + node|z16-[amenity=pharmacy], {icon-image: pharmacy-m.svg;icon-min-distance: 20;} node|z17-[amenity=pharmacy], diff --git a/data/styles/default/include/priorities_1_BG-by-size.prio.txt b/data/styles/default/include/priorities_1_BG-by-size.prio.txt index edcf5cedc..1955be601 100644 --- a/data/styles/default/include/priorities_1_BG-by-size.prio.txt +++ b/data/styles/default/include/priorities_1_BG-by-size.prio.txt @@ -102,6 +102,7 @@ amenity-police # area z15- (also has icon z amenity-ranger_station # area z13- (also has icon z15-, caption(optional) z15-) amenity-recycling-centre # area z15- (also has icon z16-, caption(optional) z16-) amenity-social_facility # area z15- (also has icon z17-, caption(optional) z17-) +amenity-stage # area z17- (also has icon z17-, caption(optional) z17-) amenity-vehicle_inspection # area z15- (also has icon z16-, caption(optional) z16-) emergency-mountain_rescue # area z13- (also has icon z16-, caption(optional) z16-) highway-pedestrian-area # area z14- (also has line z13-, line::border z14-, pathtext z14-) diff --git a/data/styles/default/include/priorities_3_FG.prio.txt b/data/styles/default/include/priorities_3_FG.prio.txt index 7fe56ebeb..9befbf7a1 100644 --- a/data/styles/default/include/priorities_3_FG.prio.txt +++ b/data/styles/default/include/priorities_3_FG.prio.txt @@ -293,6 +293,22 @@ highway-track-tunnel # line z15- (also has line:: === 190 highway-construction # line z13- (also has pathtext z15-) +highway-construction-living_street # line z13- (also has pathtext z15-) +highway-construction-motorway # line z13- (also has pathtext z15-) +highway-construction-motorway_link # line z13- (also has pathtext z15-) +highway-construction-primary # line z13- (also has pathtext z15-) +highway-construction-primary_link # line z13- (also has pathtext z15-) +highway-construction-residential # line z13- (also has pathtext z15-) +highway-construction-road # line z13- (also has pathtext z15-) +highway-construction-secondary # line z13- (also has pathtext z15-) +highway-construction-secondary_link # line z13- (also has pathtext z15-) +highway-construction-service # line z13- (also has pathtext z15-) +highway-construction-tertiary # line z13- (also has pathtext z15-) +highway-construction-tertiary_link # line z13- (also has pathtext z15-) +highway-construction-track # line z13- (also has pathtext z15-) +highway-construction-trunk # line z13- (also has pathtext z15-) +highway-construction-trunk_link # line z13- (also has pathtext z15-) +highway-construction-unclassified # line z13- (also has pathtext z15-) leisure-track # line z15- (also has caption z16-) railway-abandoned # line z16- railway-construction # line z15- diff --git a/data/styles/default/include/priorities_4_overlays.prio.txt b/data/styles/default/include/priorities_4_overlays.prio.txt index 1d898111d..a17c766ac 100644 --- a/data/styles/default/include/priorities_4_overlays.prio.txt +++ b/data/styles/default/include/priorities_4_overlays.prio.txt @@ -838,6 +838,22 @@ attraction-maze # icon z16- (also has captio attraction-roller_coaster # icon z16- (also has caption(optional) z16-) attraction-water_slide # icon z17- (also has caption(optional) z17-) highway-construction # pathtext z15- (also has line z13-) +highway-construction-living_street # pathtext z15- (also has line z13-) +highway-construction-motorway # pathtext z15- (also has line z13-) +highway-construction-motorway_link # pathtext z15- (also has line z13-) +highway-construction-primary # pathtext z15- (also has line z13-) +highway-construction-primary_link # pathtext z15- (also has line z13-) +highway-construction-residential # pathtext z15- (also has line z13-) +highway-construction-road # pathtext z15- (also has line z13-) +highway-construction-secondary # pathtext z15- (also has line z13-) +highway-construction-secondary_link # pathtext z15- (also has line z13-) +highway-construction-service # pathtext z15- (also has line z13-) +highway-construction-tertiary # pathtext z15- (also has line z13-) +highway-construction-tertiary_link # pathtext z15- (also has line z13-) +highway-construction-track # pathtext z15- (also has line z13-) +highway-construction-trunk # pathtext z15- (also has line z13-) +highway-construction-trunk_link # pathtext z15- (also has line z13-) +highway-construction-unclassified # pathtext z15- (also has line z13-) highway-living_street # pathtext z14- (also has line z12-, line::border z14-) highway-living_street-bridge # pathtext z14- (also has line z12-, line::border z14-) highway-living_street-tunnel # pathtext z14- (also has line z12-, line::border z14-, line(casing) z16-) @@ -997,6 +1013,7 @@ amenity-payment_centre # icon z17- (also has captio amenity-prep_school # icon z17- (also has caption(optional) z17-) amenity-recycling-centre # icon z16- (also has caption(optional) z16-, area z15-) amenity-sailing_school # icon z17- (also has caption(optional) z17-) +amenity-stage # icon z17- (also has caption(optional) z17-, area z17-) amenity-veterinary # icon z16- (also has caption(optional) z16-) craft-electrician # icon z17- (also has caption(optional) z18-) craft-electronics_repair # icon z17- (also has caption(optional) z18-) @@ -2088,6 +2105,7 @@ natural-tree # icon z17- (also has captio # amenity-prep_school # caption(optional) z17- (also has icon z17-) # amenity-recycling-centre # caption(optional) z16- (also has icon z16-, area z15-) # amenity-sailing_school # caption(optional) z17- (also has icon z17-) +# amenity-stage # caption(optional) z17- (also has icon z17-, area z17-) # amenity-veterinary # caption(optional) z16- (also has icon z16-) # craft-electrician # caption(optional) z18- (also has icon z17-) # craft-electronics_repair # caption(optional) z18- (also has icon z17-) diff --git a/data/styles/default/light/symbols/stage-m.svg b/data/styles/default/light/symbols/stage-m.svg new file mode 100644 index 000000000..d29a3c427 --- /dev/null +++ b/data/styles/default/light/symbols/stage-m.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/data/styles/outdoors/include/priorities_1_BG-by-size.prio.txt b/data/styles/outdoors/include/priorities_1_BG-by-size.prio.txt index 6bd26284d..13e84a6e9 100644 --- a/data/styles/outdoors/include/priorities_1_BG-by-size.prio.txt +++ b/data/styles/outdoors/include/priorities_1_BG-by-size.prio.txt @@ -102,6 +102,7 @@ amenity-police # area z15- (also has icon z amenity-ranger_station # area z13- (also has icon z13-, caption(optional) z14-) amenity-recycling-centre # area z15- (also has icon z16-, caption(optional) z16-) amenity-social_facility # area z15- (also has icon z17-, caption(optional) z17-) +amenity-stage # area z17- (also has icon z17-, caption(optional) z17-) amenity-vehicle_inspection # area z15- (also has icon z16-, caption(optional) z16-) emergency-mountain_rescue # area z13- (also has icon z12-, caption(optional) z12-) highway-pedestrian-area # area z14- (also has line z13-, line::border z14-, pathtext z14-) diff --git a/data/styles/outdoors/include/priorities_3_FG.prio.txt b/data/styles/outdoors/include/priorities_3_FG.prio.txt index c9dd78f72..0c0e76124 100644 --- a/data/styles/outdoors/include/priorities_3_FG.prio.txt +++ b/data/styles/outdoors/include/priorities_3_FG.prio.txt @@ -295,6 +295,22 @@ highway-track-tunnel # line z11- (also has line:: === 190 highway-construction # line z11- (also has pathtext z15-) +highway-construction-living_street # line z11- (also has pathtext z15-) +highway-construction-motorway # line z11- (also has pathtext z15-) +highway-construction-motorway_link # line z11- (also has pathtext z15-) +highway-construction-primary # line z11- (also has pathtext z15-) +highway-construction-primary_link # line z11- (also has pathtext z15-) +highway-construction-residential # line z11- (also has pathtext z15-) +highway-construction-road # line z11- (also has pathtext z15-) +highway-construction-secondary # line z11- (also has pathtext z15-) +highway-construction-secondary_link # line z11- (also has pathtext z15-) +highway-construction-service # line z11- (also has pathtext z15-) +highway-construction-tertiary # line z11- (also has pathtext z15-) +highway-construction-tertiary_link # line z11- (also has pathtext z15-) +highway-construction-track # line z11- (also has pathtext z15-) +highway-construction-trunk # line z11- (also has pathtext z15-) +highway-construction-trunk_link # line z11- (also has pathtext z15-) +highway-construction-unclassified # line z11- (also has pathtext z15-) leisure-track # line z15- (also has caption z16-) railway-abandoned # line z13- railway-construction # line z13- diff --git a/data/styles/outdoors/include/priorities_4_overlays.prio.txt b/data/styles/outdoors/include/priorities_4_overlays.prio.txt index 1785479cc..a84009c40 100644 --- a/data/styles/outdoors/include/priorities_4_overlays.prio.txt +++ b/data/styles/outdoors/include/priorities_4_overlays.prio.txt @@ -838,6 +838,22 @@ attraction-maze # icon z16- (also has captio attraction-roller_coaster # icon z16- (also has caption(optional) z16-) attraction-water_slide # icon z17- (also has caption(optional) z17-) highway-construction # pathtext z15- (also has line z11-) +highway-construction-living_street # pathtext z15- (also has line z11-) +highway-construction-motorway # pathtext z15- (also has line z11-) +highway-construction-motorway_link # pathtext z15- (also has line z11-) +highway-construction-primary # pathtext z15- (also has line z11-) +highway-construction-primary_link # pathtext z15- (also has line z11-) +highway-construction-residential # pathtext z15- (also has line z11-) +highway-construction-road # pathtext z15- (also has line z11-) +highway-construction-secondary # pathtext z15- (also has line z11-) +highway-construction-secondary_link # pathtext z15- (also has line z11-) +highway-construction-service # pathtext z15- (also has line z11-) +highway-construction-tertiary # pathtext z15- (also has line z11-) +highway-construction-tertiary_link # pathtext z15- (also has line z11-) +highway-construction-track # pathtext z15- (also has line z11-) +highway-construction-trunk # pathtext z15- (also has line z11-) +highway-construction-trunk_link # pathtext z15- (also has line z11-) +highway-construction-unclassified # pathtext z15- (also has line z11-) highway-living_street # pathtext z14- (also has line z12-, line::border z12-) highway-living_street-bridge # pathtext z14- (also has line z12-, line::border z12-) highway-living_street-tunnel # pathtext z14- (also has line z12-, line::border z12-, line(casing) z16-) @@ -997,6 +1013,7 @@ amenity-payment_centre # icon z17- (also has captio amenity-prep_school # icon z17- (also has caption(optional) z17-) amenity-recycling-centre # icon z16- (also has caption(optional) z16-, area z15-) amenity-sailing_school # icon z17- (also has caption(optional) z17-) +amenity-stage # icon z17- (also has caption(optional) z17-, area z17-) amenity-veterinary # icon z16- (also has caption(optional) z16-) craft-electrician # icon z17- (also has caption(optional) z18-) craft-electronics_repair # icon z17- (also has caption(optional) z18-) @@ -2091,6 +2108,7 @@ natural-tree # icon z15- (also has captio # amenity-prep_school # caption(optional) z17- (also has icon z17-) # amenity-recycling-centre # caption(optional) z16- (also has icon z16-, area z15-) # amenity-sailing_school # caption(optional) z17- (also has icon z17-) +# amenity-stage # caption(optional) z17- (also has icon z17-, area z17-) # amenity-veterinary # caption(optional) z16- (also has icon z16-) # craft-electrician # caption(optional) z18- (also has icon z17-) # craft-electronics_repair # caption(optional) z18- (also has icon z17-) diff --git a/data/styles/vehicle/include/priorities_3_FG.prio.txt b/data/styles/vehicle/include/priorities_3_FG.prio.txt index 2a2904281..9068150fe 100644 --- a/data/styles/vehicle/include/priorities_3_FG.prio.txt +++ b/data/styles/vehicle/include/priorities_3_FG.prio.txt @@ -271,6 +271,22 @@ highway-track-no-access # line z16- === 130 highway-construction # line z13- +highway-construction-living_street # line z13- +highway-construction-motorway # line z13- +highway-construction-motorway_link # line z13- +highway-construction-primary # line z13- +highway-construction-primary_link # line z13- +highway-construction-residential # line z13- +highway-construction-road # line z13- +highway-construction-secondary # line z13- +highway-construction-secondary_link # line z13- +highway-construction-service # line z13- +highway-construction-tertiary # line z13- +highway-construction-tertiary_link # line z13- +highway-construction-track # line z13- +highway-construction-trunk # line z13- +highway-construction-trunk_link # line z13- +highway-construction-unclassified # line z13- railway-abandoned # line z16- railway-construction # line z16- railway-disused # line z16- diff --git a/generator/address_enricher.cpp b/generator/address_enricher.cpp index 804ed224f..884704f7c 100644 --- a/generator/address_enricher.cpp +++ b/generator/address_enricher.cpp @@ -4,7 +4,9 @@ #include "search/house_numbers_matcher.hpp" +#include "indexer/custom_keyvalue.hpp" #include "indexer/ftypes_matcher.hpp" +#include "indexer/imported_source.hpp" #include "indexer/search_string_utils.hpp" #include "geometry/distance_on_sphere.hpp" @@ -107,6 +109,14 @@ void AddressEnricher::ProcessRawEntries(std::string const & path, TFBCollectFn c { FileReader reader(path); ReaderSource src(reader); + + CHECK_GREATER_OR_EQUAL(src.Size(), 2, ("tempaddr file too small or empty:", path)); + uint8_t const magic = ReadPrimitiveFromSource(src); + CHECK_EQUAL(magic, kTempAddrMagic, + ("Old-format tempaddr file. Delete cached .tempaddr files and regenerate:", path)); + uint8_t const version = ReadPrimitiveFromSource(src); + CHECK_EQUAL(version, kTempAddrVersion, ("Unsupported tempaddr version:", version, path)); + while (src.Size()) { Entry e; @@ -119,25 +129,17 @@ void AddressEnricher::ProcessRawEntries(std::string const & path, TFBCollectFn c for (auto const i : iPoints) e.m_points.push_back(Int64ToPointObsolete(i, kPointCoordBits)); - auto const res = Match(e); - if (!res.street) - { - ++m_stats.m_noStreet; - LOG(LDEBUG, ("No street found:", e.m_street, mercator::ToLatLon(e.m_points.front()))); - continue; - } - if (res.interpol) - { - ++m_stats.m_existInterpol; - continue; - } - auto const addNode = [&](m2::PointD const & p, std::string hn) { feature::FeatureBuilder fb; fb.SetCenter(p); fb.SetType(m_addrType); + { + indexer::CustomKeyValue kv; + kv.Add(indexer::kOpenAddressesEditableKey, e.m_editable ? 1 : 0); + fb.GetMetadata().Set(feature::Metadata::FMD_CUSTOM_IDS, kv.ToString()); + } auto & params = fb.GetParams(); params.SetStreet(e.m_street); params.SetPostcode(e.m_postcode); @@ -149,15 +151,45 @@ void AddressEnricher::ProcessRawEntries(std::string const & path, TFBCollectFn c fn(std::move(fb)); }; + if (e.GetHNRange() == Entry::kInvalidRange) + { + // Alphanumeric HNs can't be range-matched or interpolated; emit single-point entries directly. + if (e.m_points.size() == 1) + { + ++m_stats.m_addedSingle; + auto const hn = (e.m_from == e.m_to) ? e.m_from : e.m_from + " - " + e.m_to; + addNode(e.m_points.front(), hn); + } + else + LOG(LDEBUG, ("Invalid HN range for multi-point entry, skipping:", e.m_from, e.m_to, e.m_street)); + continue; + } + + auto const res = Match(e); + if (!res.street) + { + ++m_stats.m_noStreet; + LOG(LDEBUG, ("No street found:", e.m_street, mercator::ToLatLon(e.m_points.front()))); + continue; + } + if (res.interpol) + { + ++m_stats.m_existInterpol; + continue; + } + if (e.m_points.size() == 1) { if (!res.from && !res.to && res.addrsInside == 0) { ++m_stats.m_addedSingle; - addNode(e.m_points.front(), e.m_from + " - " + e.m_to); + auto const hn = (e.m_from == e.m_to) ? e.m_from : e.m_from + " - " + e.m_to; + addNode(e.m_points.front(), hn); } else + { ++m_stats.m_existSingle; + } } else { diff --git a/generator/address_enricher.hpp b/generator/address_enricher.hpp index b8df2d8f3..62a0f5658 100644 --- a/generator/address_enricher.hpp +++ b/generator/address_enricher.hpp @@ -20,10 +20,15 @@ class AddressEnricher static double constexpr kDistanceThresholdM = 50.0; public: + // .tempaddr file-format header: magic byte + version. + static constexpr uint8_t kTempAddrMagic = 0xFF; + static constexpr uint8_t kTempAddrVersion = 1; + struct RawEntryBase { std::string m_from, m_to, m_street, m_postcode; feature::InterpolType m_interpol = feature::InterpolType::None; + bool m_editable = true; /// @name Used to compare house numbers by its integer value. /// @{ @@ -41,6 +46,7 @@ class AddressEnricher rw::Write(sink, m_postcode); WriteToSink(sink, static_cast(m_interpol)); + WriteToSink(sink, static_cast(m_editable ? 1 : 0)); } template @@ -52,6 +58,7 @@ class AddressEnricher rw::Read(src, m_postcode); m_interpol = static_cast(ReadPrimitiveFromSource(src)); + m_editable = ReadPrimitiveFromSource(src) != 0; } }; diff --git a/generator/address_parser/processor.cpp b/generator/address_parser/processor.cpp index 230761c01..2743214e0 100644 --- a/generator/address_parser/processor.cpp +++ b/generator/address_parser/processor.cpp @@ -1,5 +1,6 @@ #include "processor.hpp" +#include "generator/address_enricher.hpp" #include "tiger_parser.hpp" #include "geometry/mercator.hpp" @@ -22,6 +23,11 @@ Processor::Processor(std::string const & dataPath, std::string const & outputPat FileWriter & Processor::GetWriter(std::string const & country) { auto res = m_country2writer.try_emplace(country, base::JoinPath(m_outputPath, country) + TEMP_ADDR_EXTENSION); + if (res.second) + { + uint8_t const header[2] = {generator::AddressEnricher::kTempAddrMagic, generator::AddressEnricher::kTempAddrVersion}; + res.first->second.Write(header, 2); + } return res.first->second; } diff --git a/generator/generator_tests/addresses_tests.cpp b/generator/generator_tests/addresses_tests.cpp index 7101685d5..5431becfd 100644 --- a/generator/generator_tests/addresses_tests.cpp +++ b/generator/generator_tests/addresses_tests.cpp @@ -1,6 +1,19 @@ #include "testing/testing.hpp" +#include "generator/address_enricher.hpp" #include "generator/addresses_collector.hpp" +#include "generator/generator_tests_support/test_with_classificator.hpp" + +#include "platform/platform_tests_support/scoped_file.hpp" + +#include "coding/file_writer.hpp" +#include "coding/point_coding.hpp" +#include "coding/read_write_utils.hpp" + +#include "geometry/point2d.hpp" + +using generator::tests_support::TestWithClassificator; +using platform::tests_support::ScopedFile; UNIT_TEST(GenerateAddresses_AddressInfo_FormatRange) { @@ -18,3 +31,51 @@ UNIT_TEST(GenerateAddresses_AddressInfo_FormatRange) info.m_house2 = "bar"; TEST_EQUAL(info.FormatRange(), "", ()); } + +UNIT_TEST(AddressEnricher_GetHNRange_Alphanumeric) +{ + using RawEntry = generator::AddressEnricher::RawEntryBase; + RawEntry e; + + e.m_from = "100"; e.m_to = "198"; + TEST_NOT_EQUAL(e.GetHNRange(), RawEntry::kInvalidRange, ()); + + e.m_from = "1"; e.m_to = "1"; + TEST_NOT_EQUAL(e.GetHNRange(), RawEntry::kInvalidRange, ()); + + e.m_from = "123A"; e.m_to = "123A"; + TEST_NOT_EQUAL(e.GetHNRange(), RawEntry::kInvalidRange, ()); + TEST_EQUAL(e.GetHNRange(), std::make_pair(uint64_t(123), uint64_t(123)), ()); + + e.m_from = "foo"; e.m_to = "bar"; + TEST_EQUAL(e.GetHNRange(), RawEntry::kInvalidRange, ()); +} + +UNIT_CLASS_TEST(TestWithClassificator, AddressEnricher_TempAddrFormat_Valid) +{ + using namespace generator; + + ScopedFile sf("test_format_header.tempaddr", ScopedFile::Mode::DoNotCreate); + { + FileWriter w(sf.GetFullPath()); + uint8_t const header[2] = {AddressEnricher::kTempAddrMagic, AddressEnricher::kTempAddrVersion}; + w.Write(header, 2); + + AddressEnricher::RawEntryBase e; + e.m_from = "12A"; + e.m_to = "12A"; + e.m_street = "Test St"; + e.m_postcode = "V1A 1A1"; + e.m_interpol = feature::InterpolType::None; + e.m_editable = true; + e.Save(w); + + std::vector const pts = {PointToInt64Obsolete({0.0, 0.0}, kPointCoordBits)}; + rw::Write(w, pts); + } + + AddressEnricher enricher; + int count = 0; + enricher.ProcessRawEntries(sf.GetFullPath(), [&count](feature::FeatureBuilder const &) { ++count; }); + TEST_EQUAL(count, 1, ()); +} diff --git a/generator/generator_tests/tag_admixer_test.cpp b/generator/generator_tests/tag_admixer_test.cpp index f11b31a1c..4ed19aca4 100644 --- a/generator/generator_tests/tag_admixer_test.cpp +++ b/generator/generator_tests/tag_admixer_test.cpp @@ -2,6 +2,8 @@ #include "generator/tag_admixer.hpp" +#include "indexer/osm_element.hpp" + #include "platform/platform_tests_support/scoped_file.hpp" #include @@ -58,6 +60,93 @@ UNIT_TEST(CapitalsParserTests) TEST(capitals.find(140247101) == capitals.end(), ()); } +UNIT_TEST(JunctionRefEnricher_PropagatesJunctionRefFromNodeToWay) +{ + JunctionRefEnricher enricher; + + // Node: highway=motorway_junction with junction:ref + OsmElement node; + node.m_type = OsmElement::EntityType::Node; + node.m_id = 42; + node.AddTag("highway", "motorway_junction"); + node.AddTag("junction:ref", "17B"); + enricher.Process(node); + + // Way: highway=motorway_link whose first node is the junction node + OsmElement way; + way.m_type = OsmElement::EntityType::Way; + way.m_id = 100; + way.AddTag("highway", "motorway_link"); + way.m_nodes = {42, 43, 44}; + enricher.Process(way); + + TEST_EQUAL(way.GetTag("junction:ref"), "17B", ()); +} + +UNIT_TEST(JunctionRefEnricher_FallsBackToPlainRef) +{ + JunctionRefEnricher enricher; + + OsmElement node; + node.m_type = OsmElement::EntityType::Node; + node.m_id = 55; + node.AddTag("highway", "motorway_junction"); + node.AddTag("ref", "5"); + enricher.Process(node); + + OsmElement way; + way.m_type = OsmElement::EntityType::Way; + way.m_id = 200; + way.AddTag("highway", "motorway_link"); + way.m_nodes = {55, 56}; + enricher.Process(way); + + TEST_EQUAL(way.GetTag("junction:ref"), "5", ()); +} + +UNIT_TEST(JunctionRefEnricher_DoesNotOverwriteExistingRef) +{ + JunctionRefEnricher enricher; + + OsmElement node; + node.m_type = OsmElement::EntityType::Node; + node.m_id = 77; + node.AddTag("highway", "motorway_junction"); + node.AddTag("junction:ref", "99"); + enricher.Process(node); + + OsmElement way; + way.m_type = OsmElement::EntityType::Way; + way.m_id = 300; + way.AddTag("highway", "motorway_link"); + way.AddTag("junction:ref", "existing"); + way.m_nodes = {77, 78}; + enricher.Process(way); + + TEST_EQUAL(way.GetTag("junction:ref"), "existing", ()); +} + +UNIT_TEST(JunctionRefEnricher_IgnoresNonLinkWays) +{ + JunctionRefEnricher enricher; + + OsmElement node; + node.m_type = OsmElement::EntityType::Node; + node.m_id = 88; + node.AddTag("highway", "motorway_junction"); + node.AddTag("junction:ref", "7"); + enricher.Process(node); + + OsmElement way; + way.m_type = OsmElement::EntityType::Way; + way.m_id = 400; + way.AddTag("highway", "motorway"); + way.m_nodes = {88, 89}; + enricher.Process(way); + + TEST(way.GetTag("junction:ref").empty(), ()); +} + UNIT_TEST(TagsReplacer_Smoke) { { diff --git a/generator/osm2meta.cpp b/generator/osm2meta.cpp index 056b6679f..f3bc8cd07 100644 --- a/generator/osm2meta.cpp +++ b/generator/osm2meta.cpp @@ -400,9 +400,18 @@ std::string MetadataTagProcessorImpl::ValidateAndFormat_brand(std::string const return v; } -std::string MetadataTagProcessorImpl::ValidateAndFormat_capacity(std::string const & v) +std::string MetadataTagProcessorImpl::ValidateAndFormat_capacity(std::string v) { - return v; + strings::AsciiToLower(v); + if (v == "yes" || v == "no") + return v; + + strings::NormalizeDigits(v); + unsigned int i = 0; + if (strings::to_uint(v, i)) + return v; + else + return {}; } std::string MetadataTagProcessorImpl::ValidateAndFormat_local_ref(std::string const & v) @@ -664,6 +673,8 @@ void MetadataTagProcessor::operator()(std::string const & k, std::string const & case Metadata::FMD_OUTDOOR_SEATING: valid = ValidateAndFormat_outdoor_seating(v); break; case Metadata::FMD_NETWORK: valid = ValidateAndFormat_operator(v); break; case Metadata::FMD_CHARGE_SOCKETS: m_chargeSockets.AggregateChargeSocketKey(k, v); break; + case Metadata::FMD_CAPACITY_DISABLED: valid = ValidateAndFormat_capacity(v); break; + case Metadata::FMD_CAPACITY_CHARGING: valid = ValidateAndFormat_capacity(v); break; // Metadata types we do not get from OSM. case Metadata::FMD_CUISINE: diff --git a/generator/osm2meta.hpp b/generator/osm2meta.hpp index db53898e6..31c81063c 100644 --- a/generator/osm2meta.hpp +++ b/generator/osm2meta.hpp @@ -42,7 +42,7 @@ struct MetadataTagProcessorImpl std::string ValidateAndFormat_airport_iata(std::string const & v) const; static std::string ValidateAndFormat_brand(std::string const & v); std::string ValidateAndFormat_duration(std::string const & v) const; - static std::string ValidateAndFormat_capacity(std::string const & v); + static std::string ValidateAndFormat_capacity(std::string v); static std::string ValidateAndFormat_rooms(std::string const & v); static std::string ValidateAndFormat_charge(std::string v); static std::string ValidateAndFormat_drive_through(std::string v); diff --git a/generator/road_access_generator.cpp b/generator/road_access_generator.cpp index 9c5707c14..0420e0967 100644 --- a/generator/road_access_generator.cpp +++ b/generator/road_access_generator.cpp @@ -220,6 +220,7 @@ RoadAccessTagProcessor::RoadAccessTagProcessor(VehicleType vehicleType) : m_vehi switch (vehicleType) { case VehicleType::Car: + case VehicleType::Decoder: // Order is important here starting from most specific (motorcar) to generic (access). m_accessMappings.push_back(&kMotorCarTagMapping); m_accessMappings.push_back(&kMotorVehicleTagMapping); diff --git a/generator/routing_index_generator.cpp b/generator/routing_index_generator.cpp index c64982893..74d9564c3 100644 --- a/generator/routing_index_generator.cpp +++ b/generator/routing_index_generator.cpp @@ -22,6 +22,7 @@ #include "routing_common/bicycle_model.hpp" #include "routing_common/car_model.hpp" +#include "routing_common/decoder_model.hpp" #include "routing_common/pedestrian_model.hpp" #include "indexer/classificator.hpp" @@ -62,19 +63,17 @@ class VehicleMaskBuilder final : m_pedestrianModel(PedestrianModelFactory(countryParentNameGetterFn).GetVehicleModelForCountry(country)) , m_bicycleModel(BicycleModelFactory(countryParentNameGetterFn).GetVehicleModelForCountry(country)) , m_carModel(CarModelFactory(countryParentNameGetterFn).GetVehicleModelForCountry(country)) - , m_constructionType(classif().GetTypeByPath({"highway", "construction"})) + , m_decoderModel(DecoderModelFactory(countryParentNameGetterFn).GetVehicleModelForCountry(country)) { CHECK(m_pedestrianModel, ()); CHECK(m_bicycleModel, ()); CHECK(m_carModel, ()); + CHECK(m_decoderModel, ()); } VehicleMask CalcRoadMask(FeatureType & f) const { feature::TypesHolder const types(f); - if (types.HasWithSubclass(m_constructionType)) - return 0; - return CalcMask([&](VehicleModelInterface const & model) { return model.IsRoad(types); }); } @@ -95,6 +94,8 @@ class VehicleMaskBuilder final mask |= kBicycleMask; if (fn(*m_carModel)) mask |= kCarMask; + if (fn(*m_decoderModel)) + mask |= kDecoderMask; return mask; } @@ -102,8 +103,7 @@ class VehicleMaskBuilder final std::shared_ptr const m_pedestrianModel; std::shared_ptr const m_bicycleModel; std::shared_ptr const m_carModel; - - uint32_t const m_constructionType; + std::shared_ptr const m_decoderModel; }; class Processor final diff --git a/generator/tag_admixer.hpp b/generator/tag_admixer.hpp index cb636961c..5c8a3cd10 100644 --- a/generator/tag_admixer.hpp +++ b/generator/tag_admixer.hpp @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include class WaysParserHelper @@ -286,3 +288,49 @@ class OsmTagMixer private: std::map, std::vector> m_elements; }; + +class JunctionRefEnricher +{ +public: + void Process(OsmElement & element) + { + if (element.m_type == OsmElement::EntityType::Node) + { + if (element.GetTag("highway") != "motorway_junction") + return; + + // Prefer junction:ref; fall back to plain ref (the same value on well-tagged nodes). + auto ref = element.GetTag("junction:ref"); + if (ref.empty()) + ref = element.GetTag("ref"); + if (ref.empty()) + return; + + std::lock_guard lock(m_mutex); + m_junctionNodes[element.m_id] = std::move(ref); + } + else if (element.m_type == OsmElement::EntityType::Way) + { + if (element.m_nodes.empty()) + return; + // Only propagate to link roads branching off a motorway junction. + if (element.GetTag("highway").find("_link") == std::string::npos) + return; + // Don't overwrite an explicit junction:ref already on the way. + if (!element.GetTag("junction:ref").empty()) + return; + + std::lock_guard lock(m_mutex); + // Check front (normal direction) and back (oneway=-1 reversed ways). + auto it = m_junctionNodes.find(element.m_nodes.front()); + if (it == m_junctionNodes.end()) + it = m_junctionNodes.find(element.m_nodes.back()); + if (it != m_junctionNodes.end()) + element.AddTag("junction:ref", it->second); + } + } + +private: + std::mutex m_mutex; + std::unordered_map m_junctionNodes; +}; diff --git a/generator/translator_country.cpp b/generator/translator_country.cpp index cd47c9a05..b44cc0edd 100644 --- a/generator/translator_country.cpp +++ b/generator/translator_country.cpp @@ -79,6 +79,7 @@ TranslatorCountry::TranslatorCountry(std::shared_ptr , m_tagAdmixer(std::make_shared(info.GetIntermediateFileName("ways", ".csv"), info.GetIntermediateFileName(TOWNS_FILE))) , m_tagReplacer(std::make_shared(base::JoinPath(GetPlatform().ResourcesDir(), REPLACED_TAGS_FILE))) + , m_junctionRefEnricher(std::make_shared()) { /// @todo This option is not used, but may be useful in future? // if (needMixTags) @@ -134,6 +135,7 @@ std::shared_ptr TranslatorCountry::Clone() const copy->m_tagAdmixer = m_tagAdmixer; copy->m_tagReplacer = m_tagReplacer; copy->m_osmTagMixer = m_osmTagMixer; + copy->m_junctionRefEnricher = m_junctionRefEnricher; return copy; } @@ -144,6 +146,7 @@ void TranslatorCountry::Preprocess(OsmElement & element) m_tagAdmixer->Process(element); if (m_osmTagMixer) m_osmTagMixer->Process(element); + m_junctionRefEnricher->Process(element); CollectFromRelations(element); } diff --git a/generator/translator_country.hpp b/generator/translator_country.hpp index 798ab2f59..9276fb90e 100644 --- a/generator/translator_country.hpp +++ b/generator/translator_country.hpp @@ -43,5 +43,6 @@ class TranslatorCountry : public Translator std::shared_ptr m_tagAdmixer; std::shared_ptr m_tagReplacer; std::shared_ptr m_osmTagMixer; + std::shared_ptr m_junctionRefEnricher; }; } // namespace generator diff --git a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.h b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.h index 572cd4016..8547bd265 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.h +++ b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.h @@ -44,6 +44,8 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, readonly, nullable) NSString *outdoorSeating; @property(nonatomic, readonly, nullable) NSString *network; @property(nonatomic, readonly, nullable) NSString *population; +@property(nonatomic, readonly, nullable) NSString *capacityDisabled; +@property(nonatomic, readonly, nullable) NSString *capacityCharging; - (NSDate * _Nullable)getMostRecentCheckDate; diff --git a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.mm b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.mm index c7c6e2be7..2496334ad 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.mm +++ b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageInfoData.mm @@ -138,10 +138,26 @@ - (instancetype)initWithRawData:(Info const &)rawData ohLocalization:(id + + + + + + + + + Weight/Scale Variations + Ultralight + Thin + Light + Regular + Medium + Semibold + Bold + Heavy + Black + + + + + + + + + + + Design Variations + Symbols are supported in up to nine weights and three scales. + For optimal layout with text and other symbols, vertically align + symbols with the adjacent text. + + + + + + Margins + Leading and trailing margins on the left and right side of each symbol + can be adjusted by modifying the x-location of the margin guidelines. + Modifications are automatically applied proportionally to all + scales and weights. + + + + Exporting + Symbols should be outlined when exporting to ensure the + design is preserved when submitting to Xcode. + Template v.7.0 + Requires Xcode 26 or greater + Generated from viewfinder + Typeset at 100.0 points + Small + Medium + Large + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/Maps/Images.xcassets/Interface/Symbols/powerplug.portrait.viewfinder.symbolset/Contents.json b/iphone/Maps/Images.xcassets/Interface/Symbols/powerplug.portrait.viewfinder.symbolset/Contents.json new file mode 100644 index 000000000..ab1bcd364 --- /dev/null +++ b/iphone/Maps/Images.xcassets/Interface/Symbols/powerplug.portrait.viewfinder.symbolset/Contents.json @@ -0,0 +1,12 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "symbols" : [ + { + "filename" : "powerplug.portrait.viewfinder.svg", + "idiom" : "universal" + } + ] +} diff --git a/iphone/Maps/Images.xcassets/Interface/Symbols/powerplug.portrait.viewfinder.symbolset/powerplug.portrait.viewfinder.svg b/iphone/Maps/Images.xcassets/Interface/Symbols/powerplug.portrait.viewfinder.symbolset/powerplug.portrait.viewfinder.svg new file mode 100644 index 000000000..edc016ef7 --- /dev/null +++ b/iphone/Maps/Images.xcassets/Interface/Symbols/powerplug.portrait.viewfinder.symbolset/powerplug.portrait.viewfinder.svg @@ -0,0 +1,109 @@ + + + + + + + + + + Weight/Scale Variations + Ultralight + Thin + Light + Regular + Medium + Semibold + Bold + Heavy + Black + + + + + + + + + + + Design Variations + Symbols are supported in up to nine weights and three scales. + For optimal layout with text and other symbols, vertically align + symbols with the adjacent text. + + + + + + Margins + Leading and trailing margins on the left and right side of each symbol + can be adjusted by modifying the x-location of the margin guidelines. + Modifications are automatically applied proportionally to all + scales and weights. + + + + Exporting + Symbols should be outlined when exporting to ensure the + design is preserved when submitting to Xcode. + Template v.7.0 + Requires Xcode 26 or greater + Generated from viewfinder + Typeset at 100.0 points + Small + Medium + Large + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/Maps/LocalizedStrings/af.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/af.lproj/Localizable.strings index 65415cc70..141c7588c 100644 --- a/iphone/Maps/LocalizedStrings/af.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/af.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Ja"; /* E.g. "WiFi:No" */ "no_available" = "Nee"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapasiteit: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Netwerk: %@"; "trip_finished" = "U het aangekom!"; diff --git a/iphone/Maps/LocalizedStrings/af.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/af.lproj/LocalizableTypes.strings index 5668f88fb..1d08008fe 100644 --- a/iphone/Maps/LocalizedStrings/af.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/af.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tonnel"; "type.highway.bus_stop" = "Bushalte"; "type.highway.construction" = "Pad in aanbou"; +"type.highway.construction.motorway" = "Pad in aanbou"; +"type.highway.construction.motorway_link" = "Pad in aanbou"; +"type.highway.construction.trunk" = "Pad in aanbou"; +"type.highway.construction.trunk_link" = "Pad in aanbou"; +"type.highway.construction.primary" = "Pad in aanbou"; +"type.highway.construction.primary_link" = "Pad in aanbou"; +"type.highway.construction.secondary" = "Pad in aanbou"; +"type.highway.construction.secondary_link" = "Pad in aanbou"; +"type.highway.construction.tertiary" = "Pad in aanbou"; +"type.highway.construction.tertiary_link" = "Pad in aanbou"; +"type.highway.construction.residential" = "Pad in aanbou"; +"type.highway.construction.unclassified" = "Pad in aanbou"; +"type.highway.construction.service" = "Pad in aanbou"; +"type.highway.construction.living_street" = "Pad in aanbou"; +"type.highway.construction.road" = "Pad in aanbou"; +"type.highway.construction.track" = "Pad in aanbou"; "type.highway.cycleway" = "Fietspad"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Brug"; diff --git a/iphone/Maps/LocalizedStrings/ar.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ar.lproj/Localizable.strings index 0f8c64aaf..9f5ce4418 100644 --- a/iphone/Maps/LocalizedStrings/ar.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ar.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "نعم"; /* E.g. "WiFi:No" */ "no_available" = "لا"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "السعة: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "الشبكة: %@"; "trip_finished" = "لقد وصلت!"; diff --git a/iphone/Maps/LocalizedStrings/ar.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/ar.lproj/LocalizableTypes.strings index d70392789..219747a83 100644 --- a/iphone/Maps/LocalizedStrings/ar.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/ar.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "نفق"; "type.highway.bus_stop" = "موقف حافلات"; "type.highway.construction" = "طريق تحت الإنشاء"; +"type.highway.construction.motorway" = "طريق تحت الإنشاء"; +"type.highway.construction.motorway_link" = "طريق تحت الإنشاء"; +"type.highway.construction.trunk" = "طريق تحت الإنشاء"; +"type.highway.construction.trunk_link" = "طريق تحت الإنشاء"; +"type.highway.construction.primary" = "طريق تحت الإنشاء"; +"type.highway.construction.primary_link" = "طريق تحت الإنشاء"; +"type.highway.construction.secondary" = "طريق تحت الإنشاء"; +"type.highway.construction.secondary_link" = "طريق تحت الإنشاء"; +"type.highway.construction.tertiary" = "طريق تحت الإنشاء"; +"type.highway.construction.tertiary_link" = "طريق تحت الإنشاء"; +"type.highway.construction.residential" = "طريق تحت الإنشاء"; +"type.highway.construction.unclassified" = "طريق تحت الإنشاء"; +"type.highway.construction.service" = "طريق تحت الإنشاء"; +"type.highway.construction.living_street" = "طريق تحت الإنشاء"; +"type.highway.construction.road" = "طريق تحت الإنشاء"; +"type.highway.construction.track" = "طريق تحت الإنشاء"; "type.highway.cycleway" = "مسار للدراجات"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "جسر"; diff --git a/iphone/Maps/LocalizedStrings/az.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/az.lproj/Localizable.strings index c487815c3..8afafbfac 100644 --- a/iphone/Maps/LocalizedStrings/az.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/az.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Var"; /* E.g. "WiFi:No" */ "no_available" = "Yox"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Tutumu: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Şəbəkə: %@"; "trip_finished" = "Sən gəldin!"; diff --git a/iphone/Maps/LocalizedStrings/az.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/az.lproj/LocalizableTypes.strings index 7719763a1..7dc462b4d 100644 --- a/iphone/Maps/LocalizedStrings/az.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/az.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunel"; "type.highway.bus_stop" = "Avtobus dayanacağı"; "type.highway.construction" = "Tikili Yol"; +"type.highway.construction.motorway" = "Tikili Yol"; +"type.highway.construction.motorway_link" = "Tikili Yol"; +"type.highway.construction.trunk" = "Tikili Yol"; +"type.highway.construction.trunk_link" = "Tikili Yol"; +"type.highway.construction.primary" = "Tikili Yol"; +"type.highway.construction.primary_link" = "Tikili Yol"; +"type.highway.construction.secondary" = "Tikili Yol"; +"type.highway.construction.secondary_link" = "Tikili Yol"; +"type.highway.construction.tertiary" = "Tikili Yol"; +"type.highway.construction.tertiary_link" = "Tikili Yol"; +"type.highway.construction.residential" = "Tikili Yol"; +"type.highway.construction.unclassified" = "Tikili Yol"; +"type.highway.construction.service" = "Tikili Yol"; +"type.highway.construction.living_street" = "Tikili Yol"; +"type.highway.construction.road" = "Tikili Yol"; +"type.highway.construction.track" = "Tikili Yol"; "type.highway.cycleway" = "Velosiped yolu"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Körpü"; diff --git a/iphone/Maps/LocalizedStrings/be.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/be.lproj/Localizable.strings index b323ec604..b595b3cc5 100644 --- a/iphone/Maps/LocalizedStrings/be.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/be.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Ёсць"; /* E.g. "WiFi:No" */ "no_available" = "Няма"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Ёмістасць: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Сетка: %@"; "trip_finished" = "Вы прыбылі!"; diff --git a/iphone/Maps/LocalizedStrings/bg.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/bg.lproj/Localizable.strings index 0144f9a89..d53aba7a1 100644 --- a/iphone/Maps/LocalizedStrings/bg.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/bg.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Да"; /* E.g. "WiFi:No" */ "no_available" = "Не"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Капацитет: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Мрежа: %@"; "trip_finished" = "Пристигнахте!"; diff --git a/iphone/Maps/LocalizedStrings/bg.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/bg.lproj/LocalizableTypes.strings index ea72fe3a5..614568e39 100644 --- a/iphone/Maps/LocalizedStrings/bg.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/bg.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Тунел"; "type.highway.bus_stop" = "Спирка"; "type.highway.construction" = "Път в процес на изграждане"; +"type.highway.construction.motorway" = "Път в процес на изграждане"; +"type.highway.construction.motorway_link" = "Път в процес на изграждане"; +"type.highway.construction.trunk" = "Път в процес на изграждане"; +"type.highway.construction.trunk_link" = "Път в процес на изграждане"; +"type.highway.construction.primary" = "Път в процес на изграждане"; +"type.highway.construction.primary_link" = "Път в процес на изграждане"; +"type.highway.construction.secondary" = "Път в процес на изграждане"; +"type.highway.construction.secondary_link" = "Път в процес на изграждане"; +"type.highway.construction.tertiary" = "Път в процес на изграждане"; +"type.highway.construction.tertiary_link" = "Път в процес на изграждане"; +"type.highway.construction.residential" = "Път в процес на изграждане"; +"type.highway.construction.unclassified" = "Път в процес на изграждане"; +"type.highway.construction.service" = "Път в процес на изграждане"; +"type.highway.construction.living_street" = "Път в процес на изграждане"; +"type.highway.construction.road" = "Път в процес на изграждане"; +"type.highway.construction.track" = "Път в процес на изграждане"; "type.highway.cycleway" = "Пътека за колела"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Мост"; diff --git a/iphone/Maps/LocalizedStrings/ca.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ca.lproj/Localizable.strings index 249914619..8c4f9bde0 100644 --- a/iphone/Maps/LocalizedStrings/ca.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ca.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Sí"; /* E.g. "WiFi:No" */ "no_available" = "No"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacitat: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Xarxa: %@"; "trip_finished" = "Heu arribat!"; diff --git a/iphone/Maps/LocalizedStrings/ca.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/ca.lproj/LocalizableTypes.strings index 136e865fb..a1e990f3f 100644 --- a/iphone/Maps/LocalizedStrings/ca.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/ca.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Túnel"; "type.highway.bus_stop" = "Parada d’autobús"; "type.highway.construction" = "Via en construcció"; +"type.highway.construction.motorway" = "Via en construcció"; +"type.highway.construction.motorway_link" = "Via en construcció"; +"type.highway.construction.trunk" = "Via en construcció"; +"type.highway.construction.trunk_link" = "Via en construcció"; +"type.highway.construction.primary" = "Via en construcció"; +"type.highway.construction.primary_link" = "Via en construcció"; +"type.highway.construction.secondary" = "Via en construcció"; +"type.highway.construction.secondary_link" = "Via en construcció"; +"type.highway.construction.tertiary" = "Via en construcció"; +"type.highway.construction.tertiary_link" = "Via en construcció"; +"type.highway.construction.residential" = "Via en construcció"; +"type.highway.construction.unclassified" = "Via en construcció"; +"type.highway.construction.service" = "Via en construcció"; +"type.highway.construction.living_street" = "Via en construcció"; +"type.highway.construction.road" = "Via en construcció"; +"type.highway.construction.track" = "Via en construcció"; "type.highway.cycleway" = "Carril bici"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Pont"; @@ -882,7 +898,7 @@ "type.place.country" = "País"; "type.place.county" = "Comtat"; "type.place.farm" = "Farm"; -"type.place.hamlet" = "Aldea"; +"type.place.hamlet" = "Hamlet"; "type.place.island" = "Illa"; "type.place.islet" = "Illot"; "type.place.isolated_dwelling" = "Habitatge aïllat"; @@ -900,7 +916,7 @@ /* Named part of a city or town, bigger than place=quarter (Wiki: https://wiki.openstreetmap.org/wiki/Tag:place%3Dsuburb) */ "type.place.suburb" = "Urbanització"; "type.place.town" = "Town"; -"type.place.village" = "Poble"; +"type.place.village" = "Village"; "type.power" = "Energia"; "type.power.generator" = "Generador d’energia"; "type.power.generator.solar" = "Generador solar"; @@ -1313,7 +1329,7 @@ "type.shop.tea" = "Tea Shop"; "type.shop.telecommunication" = "Telecommunication Shop"; "type.shop.ticket" = "Ticket Shop"; -"type.shop.toys" = "Botiga de joguines"; +"type.shop.toys" = "Botiga de jocs"; "type.shop.travel_agency" = "Agència de viatges"; "type.shop.tyres" = "Tyre Shop"; "type.shop.variety_store" = "Botiga de varietat"; @@ -1509,10 +1525,10 @@ /* https://wiki.openstreetmap.org/wiki/Tag:leisure=sports_hall */ "type.leisure.sports_hall" = "Pavelló esportiu"; "type.xmas.tree" = "Arbre de Nadal"; -"type.leisure.sports_centre.sport.four_square" = "Poliesportiu"; +"type.leisure.sports_centre.sport.four_square" = "Sports Centre"; "type.sport.four_square" = "Four Square"; "type.sport.boules" = "Boules"; -"type.leisure.sports_centre.sport.boules" = "Poliesportiu"; +"type.leisure.sports_centre.sport.boules" = "Sports Centre"; "type.sport.pickleball" = "Pickleball"; "type.leisure.sports_centre.sport.pickleball" = "Centre esportiu"; "type.organic.no" = "No organic options"; diff --git a/iphone/Maps/LocalizedStrings/cs.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/cs.lproj/Localizable.strings index 6162d1a28..76426f74a 100644 --- a/iphone/Maps/LocalizedStrings/cs.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/cs.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Ano"; /* E.g. "WiFi:No" */ "no_available" = "Ne"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapacita: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Síť: %@"; "trip_finished" = "Přijeli jste!"; diff --git a/iphone/Maps/LocalizedStrings/cs.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/cs.lproj/LocalizableTypes.strings index 704e41a3a..a05882e1c 100644 --- a/iphone/Maps/LocalizedStrings/cs.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/cs.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunel"; "type.highway.bus_stop" = "Autobusová zastávka"; "type.highway.construction" = "Silnice v rekonstrukci"; +"type.highway.construction.motorway" = "Silnice v rekonstrukci"; +"type.highway.construction.motorway_link" = "Silnice v rekonstrukci"; +"type.highway.construction.trunk" = "Silnice v rekonstrukci"; +"type.highway.construction.trunk_link" = "Silnice v rekonstrukci"; +"type.highway.construction.primary" = "Silnice v rekonstrukci"; +"type.highway.construction.primary_link" = "Silnice v rekonstrukci"; +"type.highway.construction.secondary" = "Silnice v rekonstrukci"; +"type.highway.construction.secondary_link" = "Silnice v rekonstrukci"; +"type.highway.construction.tertiary" = "Silnice v rekonstrukci"; +"type.highway.construction.tertiary_link" = "Silnice v rekonstrukci"; +"type.highway.construction.residential" = "Silnice v rekonstrukci"; +"type.highway.construction.unclassified" = "Silnice v rekonstrukci"; +"type.highway.construction.service" = "Silnice v rekonstrukci"; +"type.highway.construction.living_street" = "Silnice v rekonstrukci"; +"type.highway.construction.road" = "Silnice v rekonstrukci"; +"type.highway.construction.track" = "Silnice v rekonstrukci"; "type.highway.cycleway" = "Cyklostezka"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Most"; diff --git a/iphone/Maps/LocalizedStrings/da.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/da.lproj/Localizable.strings index c6262caf7..b9e4d3a48 100644 --- a/iphone/Maps/LocalizedStrings/da.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/da.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Ja"; /* E.g. "WiFi:No" */ "no_available" = "Nej"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapacitet: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Netværk: %@"; "trip_finished" = "Du er ankommet!"; diff --git a/iphone/Maps/LocalizedStrings/da.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/da.lproj/LocalizableTypes.strings index 953a48e8f..b4b32dea0 100644 --- a/iphone/Maps/LocalizedStrings/da.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/da.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunnel"; "type.highway.bus_stop" = "Busstoppested"; "type.highway.construction" = "Vej under anlæggelse"; +"type.highway.construction.motorway" = "Vej under anlæggelse"; +"type.highway.construction.motorway_link" = "Vej under anlæggelse"; +"type.highway.construction.trunk" = "Vej under anlæggelse"; +"type.highway.construction.trunk_link" = "Vej under anlæggelse"; +"type.highway.construction.primary" = "Vej under anlæggelse"; +"type.highway.construction.primary_link" = "Vej under anlæggelse"; +"type.highway.construction.secondary" = "Vej under anlæggelse"; +"type.highway.construction.secondary_link" = "Vej under anlæggelse"; +"type.highway.construction.tertiary" = "Vej under anlæggelse"; +"type.highway.construction.tertiary_link" = "Vej under anlæggelse"; +"type.highway.construction.residential" = "Vej under anlæggelse"; +"type.highway.construction.unclassified" = "Vej under anlæggelse"; +"type.highway.construction.service" = "Vej under anlæggelse"; +"type.highway.construction.living_street" = "Vej under anlæggelse"; +"type.highway.construction.road" = "Vej under anlæggelse"; +"type.highway.construction.track" = "Vej under anlæggelse"; "type.highway.cycleway" = "Cykelsti"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Bro"; diff --git a/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings index c77a5d8a8..39fed06c0 100644 --- a/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Ja"; /* E.g. "WiFi:No" */ "no_available" = "Nein"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapazität: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Netzwerk: %@"; "trip_finished" = "Du bist am Ziel angekommen!"; diff --git a/iphone/Maps/LocalizedStrings/de.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/de.lproj/LocalizableTypes.strings index 3d639d4f3..5ad08bb08 100644 --- a/iphone/Maps/LocalizedStrings/de.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/de.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunnel"; "type.highway.bus_stop" = "Bushaltestelle"; "type.highway.construction" = "Straße im Bau"; +"type.highway.construction.motorway" = "Straße im Bau"; +"type.highway.construction.motorway_link" = "Straße im Bau"; +"type.highway.construction.trunk" = "Straße im Bau"; +"type.highway.construction.trunk_link" = "Straße im Bau"; +"type.highway.construction.primary" = "Straße im Bau"; +"type.highway.construction.primary_link" = "Straße im Bau"; +"type.highway.construction.secondary" = "Straße im Bau"; +"type.highway.construction.secondary_link" = "Straße im Bau"; +"type.highway.construction.tertiary" = "Straße im Bau"; +"type.highway.construction.tertiary_link" = "Straße im Bau"; +"type.highway.construction.residential" = "Straße im Bau"; +"type.highway.construction.unclassified" = "Straße im Bau"; +"type.highway.construction.service" = "Straße im Bau"; +"type.highway.construction.living_street" = "Straße im Bau"; +"type.highway.construction.road" = "Straße im Bau"; +"type.highway.construction.track" = "Straße im Bau"; "type.highway.cycleway" = "Radweg"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Brücke"; diff --git a/iphone/Maps/LocalizedStrings/el.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/el.lproj/Localizable.strings index fbd3a97ac..2bed85384 100644 --- a/iphone/Maps/LocalizedStrings/el.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/el.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Ναι"; /* E.g. "WiFi:No" */ "no_available" = "Όχι"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Χωρητικότητα: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Δίκτυο: %@"; "trip_finished" = "Μόλις φτάσατε!"; diff --git a/iphone/Maps/LocalizedStrings/el.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/el.lproj/LocalizableTypes.strings index 0b4a7462b..4f2862d74 100644 --- a/iphone/Maps/LocalizedStrings/el.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/el.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Σήραγγα"; "type.highway.bus_stop" = "Στάση λεωφορείου"; "type.highway.construction" = "Οδός υπό κατασκευή"; +"type.highway.construction.motorway" = "Οδός υπό κατασκευή"; +"type.highway.construction.motorway_link" = "Οδός υπό κατασκευή"; +"type.highway.construction.trunk" = "Οδός υπό κατασκευή"; +"type.highway.construction.trunk_link" = "Οδός υπό κατασκευή"; +"type.highway.construction.primary" = "Οδός υπό κατασκευή"; +"type.highway.construction.primary_link" = "Οδός υπό κατασκευή"; +"type.highway.construction.secondary" = "Οδός υπό κατασκευή"; +"type.highway.construction.secondary_link" = "Οδός υπό κατασκευή"; +"type.highway.construction.tertiary" = "Οδός υπό κατασκευή"; +"type.highway.construction.tertiary_link" = "Οδός υπό κατασκευή"; +"type.highway.construction.residential" = "Οδός υπό κατασκευή"; +"type.highway.construction.unclassified" = "Οδός υπό κατασκευή"; +"type.highway.construction.service" = "Οδός υπό κατασκευή"; +"type.highway.construction.living_street" = "Οδός υπό κατασκευή"; +"type.highway.construction.road" = "Οδός υπό κατασκευή"; +"type.highway.construction.track" = "Οδός υπό κατασκευή"; "type.highway.cycleway" = "Ποδηλατόδρομος"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Γέφυρα"; diff --git a/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings index 0c1f4b4e9..c12a6c3f1 100644 --- a/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Yes"; /* E.g. "WiFi:No" */ "no_available" = "No"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacity: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Network: %@"; "trip_finished" = "You have arrived!"; @@ -878,3 +876,11 @@ "downloader_check_updates_error" = "Error checking for updates"; "editor_add_select_category_recent_subtitle" = "Recently Used"; "oh_unknown" = "Opening hours unknown"; + +/* To indicate the number of disabled spaces */ +"capacity_disabled_yes" = "Has dedicated disabled spaces"; +"capacity_disabled_no" = "No dedicated disabled spaces"; + +/* To indicate the number of charging spaces */ +"capacity_charging_yes" = "Has spaces with chargers"; +"capacity_charging_no" = "No spaces with chargers"; diff --git a/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.stringsdict b/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.stringsdict index 7ca6067ba..da9e543e5 100644 --- a/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.stringsdict +++ b/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.stringsdict @@ -88,5 +88,53 @@ %lld rooms + capacity_disabled + + NSStringLocalizedFormatKey + %#@nevertranslate@ + nevertranslate + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + lld + other + %lld dedicated disabled spaces + one + %lld dedicated disabled space + + + capacity_charging + + NSStringLocalizedFormatKey + %#@nevertranslate@ + nevertranslate + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + lld + other + %lld spaces with chargers + one + %lld space with a charger + + + capacity + + NSStringLocalizedFormatKey + %#@nevertranslate@ + nevertranslate + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + lld + other + %lld spaces + one + %lld space + + diff --git a/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings index b14f6d3a7..56b4b791f 100644 --- a/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings @@ -690,8 +690,6 @@ "yes_available" = "Yes"; /* E.g. "WiFi:No" */ "no_available" = "No"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacity: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Network: %@"; "trip_finished" = "You have arrived!"; @@ -878,4 +876,12 @@ "contribute_to_osm" = "Contribute to OpenStreetMap"; "contribute_to_osm_add_place" = "Add Place"; "contribute_to_osm_update_map" = "Update the Map to Contribute"; -"contribute_to_osm_update_map_description" = "You need to update the %@ map to the latest version before you can contribute to the OpenStreetMap data"; \ No newline at end of file +"contribute_to_osm_update_map_description" = "You need to update the %@ map to the latest version before you can contribute to the OpenStreetMap data"; + +/* To indicate the number of disabled spaces */ +"capacity_disabled_yes" = "Has dedicated disabled spaces"; +"capacity_disabled_no" = "No dedicated disabled spaces"; + +/* To indicate the number of charging spaces */ +"capacity_charging_yes" = "Has spaces with chargers"; +"capacity_charging_no" = "No spaces with chargers"; diff --git a/iphone/Maps/LocalizedStrings/en.lproj/Localizable.stringsdict b/iphone/Maps/LocalizedStrings/en.lproj/Localizable.stringsdict index f636c3701..68207e057 100644 --- a/iphone/Maps/LocalizedStrings/en.lproj/Localizable.stringsdict +++ b/iphone/Maps/LocalizedStrings/en.lproj/Localizable.stringsdict @@ -84,5 +84,53 @@ %lld room + capacity_disabled + + NSStringLocalizedFormatKey + %#@nevertranslate@ + nevertranslate + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + lld + other + %lld dedicated disabled spaces + one + %lld dedicated disabled space + + + capacity_charging + + NSStringLocalizedFormatKey + %#@nevertranslate@ + nevertranslate + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + lld + other + %lld spaces with chargers + one + %lld space with a charger + + + capacity + + NSStringLocalizedFormatKey + %#@nevertranslate@ + nevertranslate + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + lld + other + %lld spaces + one + %lld space + + diff --git a/iphone/Maps/LocalizedStrings/en.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/en.lproj/LocalizableTypes.strings index e44a3583f..ecc693b45 100644 --- a/iphone/Maps/LocalizedStrings/en.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/en.lproj/LocalizableTypes.strings @@ -1516,3 +1516,4 @@ /* https://wiki.openstreetmap.org/wiki/Tag:leisure=sports_hall */ "type.leisure.sports_hall" = "Sports hall"; "type.xmas.tree" = "Christmas Tree"; +"type.amenity.stage" = "Stage"; \ No newline at end of file diff --git a/iphone/Maps/LocalizedStrings/es-MX.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/es-MX.lproj/Localizable.strings index 56a7e5646..db7a74d7c 100644 --- a/iphone/Maps/LocalizedStrings/es-MX.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/es-MX.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Sí"; /* E.g. "WiFi:No" */ "no_available" = "No"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacidad: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Red: %@"; "trip_finished" = "¡Ya llegó!"; diff --git a/iphone/Maps/LocalizedStrings/es-MX.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/es-MX.lproj/LocalizableTypes.strings index 1eb8441e6..d1c65d8af 100644 --- a/iphone/Maps/LocalizedStrings/es-MX.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/es-MX.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Túnel"; "type.highway.bus_stop" = "Parada de autobús"; "type.highway.construction" = "Vía en construcción"; +"type.highway.construction.motorway" = "Vía en construcción"; +"type.highway.construction.motorway_link" = "Vía en construcción"; +"type.highway.construction.trunk" = "Vía en construcción"; +"type.highway.construction.trunk_link" = "Vía en construcción"; +"type.highway.construction.primary" = "Vía en construcción"; +"type.highway.construction.primary_link" = "Vía en construcción"; +"type.highway.construction.secondary" = "Vía en construcción"; +"type.highway.construction.secondary_link" = "Vía en construcción"; +"type.highway.construction.tertiary" = "Vía en construcción"; +"type.highway.construction.tertiary_link" = "Vía en construcción"; +"type.highway.construction.residential" = "Vía en construcción"; +"type.highway.construction.unclassified" = "Vía en construcción"; +"type.highway.construction.service" = "Vía en construcción"; +"type.highway.construction.living_street" = "Vía en construcción"; +"type.highway.construction.road" = "Vía en construcción"; +"type.highway.construction.track" = "Vía en construcción"; "type.highway.cycleway" = "Ciclovía"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Puente"; diff --git a/iphone/Maps/LocalizedStrings/es.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/es.lproj/Localizable.strings index 80bb363f3..405e51ee5 100644 --- a/iphone/Maps/LocalizedStrings/es.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/es.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Sí"; /* E.g. "WiFi:No" */ "no_available" = "No"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacidad: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Red: %@"; "trip_finished" = "¡Has llegado!"; diff --git a/iphone/Maps/LocalizedStrings/es.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/es.lproj/LocalizableTypes.strings index c3532bcf1..8c79a939c 100644 --- a/iphone/Maps/LocalizedStrings/es.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/es.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Túnel"; "type.highway.bus_stop" = "Parada de bus"; "type.highway.construction" = "Vía en construcción"; +"type.highway.construction.motorway" = "Vía en construcción"; +"type.highway.construction.motorway_link" = "Vía en construcción"; +"type.highway.construction.trunk" = "Vía en construcción"; +"type.highway.construction.trunk_link" = "Vía en construcción"; +"type.highway.construction.primary" = "Vía en construcción"; +"type.highway.construction.primary_link" = "Vía en construcción"; +"type.highway.construction.secondary" = "Vía en construcción"; +"type.highway.construction.secondary_link" = "Vía en construcción"; +"type.highway.construction.tertiary" = "Vía en construcción"; +"type.highway.construction.tertiary_link" = "Vía en construcción"; +"type.highway.construction.residential" = "Vía en construcción"; +"type.highway.construction.unclassified" = "Vía en construcción"; +"type.highway.construction.service" = "Vía en construcción"; +"type.highway.construction.living_street" = "Vía en construcción"; +"type.highway.construction.road" = "Vía en construcción"; +"type.highway.construction.track" = "Vía en construcción"; "type.highway.cycleway" = "Ciclovía"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Puente"; diff --git a/iphone/Maps/LocalizedStrings/et.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/et.lproj/Localizable.strings index fdc6e0daa..57fb648c7 100644 --- a/iphone/Maps/LocalizedStrings/et.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/et.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "olemas"; /* E.g. "WiFi:No" */ "no_available" = "puudub"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kohti: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Võrgustik: %@"; "trip_finished" = "Oled kohal!"; diff --git a/iphone/Maps/LocalizedStrings/et.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/et.lproj/LocalizableTypes.strings index 5b4ab5ec9..aa47fd6a9 100644 --- a/iphone/Maps/LocalizedStrings/et.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/et.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunnel"; "type.highway.bus_stop" = "Bussipeatus"; "type.highway.construction" = "Ehitusjärgus tee"; +"type.highway.construction.motorway" = "Ehitusjärgus tee"; +"type.highway.construction.motorway_link" = "Ehitusjärgus tee"; +"type.highway.construction.trunk" = "Ehitusjärgus tee"; +"type.highway.construction.trunk_link" = "Ehitusjärgus tee"; +"type.highway.construction.primary" = "Ehitusjärgus tee"; +"type.highway.construction.primary_link" = "Ehitusjärgus tee"; +"type.highway.construction.secondary" = "Ehitusjärgus tee"; +"type.highway.construction.secondary_link" = "Ehitusjärgus tee"; +"type.highway.construction.tertiary" = "Ehitusjärgus tee"; +"type.highway.construction.tertiary_link" = "Ehitusjärgus tee"; +"type.highway.construction.residential" = "Ehitusjärgus tee"; +"type.highway.construction.unclassified" = "Ehitusjärgus tee"; +"type.highway.construction.service" = "Ehitusjärgus tee"; +"type.highway.construction.living_street" = "Ehitusjärgus tee"; +"type.highway.construction.road" = "Ehitusjärgus tee"; +"type.highway.construction.track" = "Ehitusjärgus tee"; "type.highway.cycleway" = "Jalgrattatee"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Jalgrattasild"; diff --git a/iphone/Maps/LocalizedStrings/eu.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/eu.lproj/Localizable.strings index ab072d1e2..b9ed43bdd 100644 --- a/iphone/Maps/LocalizedStrings/eu.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/eu.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Bai"; /* E.g. "WiFi:No" */ "no_available" = "Ez"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Edukiera: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Sarea: %@"; "trip_finished" = "Iritsi zara!"; diff --git a/iphone/Maps/LocalizedStrings/eu.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/eu.lproj/LocalizableTypes.strings index 6d22a0339..c1a947c33 100644 --- a/iphone/Maps/LocalizedStrings/eu.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/eu.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunela"; "type.highway.bus_stop" = "Autobus geltokia"; "type.highway.construction" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.motorway" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.motorway_link" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.trunk" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.trunk_link" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.primary" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.primary_link" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.secondary" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.secondary_link" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.tertiary" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.tertiary_link" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.residential" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.unclassified" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.service" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.living_street" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.road" = "Eraikitzen ari diren errepidea"; +"type.highway.construction.track" = "Eraikitzen ari diren errepidea"; "type.highway.cycleway" = "Bidegorri edo bizikleta-bidea"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Zubia"; diff --git a/iphone/Maps/LocalizedStrings/fa.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/fa.lproj/Localizable.strings index 00dffa429..69648749c 100644 --- a/iphone/Maps/LocalizedStrings/fa.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/fa.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "بلی"; /* E.g. "WiFi:No" */ "no_available" = "خیر"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "ظرفیت: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "شبکه: %@"; "trip_finished" = "شما به مقصد رسیدید!"; diff --git a/iphone/Maps/LocalizedStrings/fa.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/fa.lproj/LocalizableTypes.strings index 8cb29e7ac..f5931ee2d 100644 --- a/iphone/Maps/LocalizedStrings/fa.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/fa.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "تونل"; "type.highway.bus_stop" = "حمل و نقل"; "type.highway.construction" = "جاده در دست ساخت است"; +"type.highway.construction.motorway" = "جاده در دست ساخت است"; +"type.highway.construction.motorway_link" = "جاده در دست ساخت است"; +"type.highway.construction.trunk" = "جاده در دست ساخت است"; +"type.highway.construction.trunk_link" = "جاده در دست ساخت است"; +"type.highway.construction.primary" = "جاده در دست ساخت است"; +"type.highway.construction.primary_link" = "جاده در دست ساخت است"; +"type.highway.construction.secondary" = "جاده در دست ساخت است"; +"type.highway.construction.secondary_link" = "جاده در دست ساخت است"; +"type.highway.construction.tertiary" = "جاده در دست ساخت است"; +"type.highway.construction.tertiary_link" = "جاده در دست ساخت است"; +"type.highway.construction.residential" = "جاده در دست ساخت است"; +"type.highway.construction.unclassified" = "جاده در دست ساخت است"; +"type.highway.construction.service" = "جاده در دست ساخت است"; +"type.highway.construction.living_street" = "جاده در دست ساخت است"; +"type.highway.construction.road" = "جاده در دست ساخت است"; +"type.highway.construction.track" = "جاده در دست ساخت است"; "type.highway.cycleway" = "Cycle Path"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "پل"; diff --git a/iphone/Maps/LocalizedStrings/fi.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/fi.lproj/Localizable.strings index 376121ff2..d79b2eb7f 100644 --- a/iphone/Maps/LocalizedStrings/fi.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/fi.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Kyllä"; /* E.g. "WiFi:No" */ "no_available" = "Ei"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapasiteetti: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Verkko: %@"; "trip_finished" = "Olet perillä!"; diff --git a/iphone/Maps/LocalizedStrings/fi.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/fi.lproj/LocalizableTypes.strings index 022a1e421..0655af193 100644 --- a/iphone/Maps/LocalizedStrings/fi.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/fi.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunneli"; "type.highway.bus_stop" = "Bussipysäkki"; "type.highway.construction" = "Rakenteilla oleva tie"; +"type.highway.construction.motorway" = "Rakenteilla oleva tie"; +"type.highway.construction.motorway_link" = "Rakenteilla oleva tie"; +"type.highway.construction.trunk" = "Rakenteilla oleva tie"; +"type.highway.construction.trunk_link" = "Rakenteilla oleva tie"; +"type.highway.construction.primary" = "Rakenteilla oleva tie"; +"type.highway.construction.primary_link" = "Rakenteilla oleva tie"; +"type.highway.construction.secondary" = "Rakenteilla oleva tie"; +"type.highway.construction.secondary_link" = "Rakenteilla oleva tie"; +"type.highway.construction.tertiary" = "Rakenteilla oleva tie"; +"type.highway.construction.tertiary_link" = "Rakenteilla oleva tie"; +"type.highway.construction.residential" = "Rakenteilla oleva tie"; +"type.highway.construction.unclassified" = "Rakenteilla oleva tie"; +"type.highway.construction.service" = "Rakenteilla oleva tie"; +"type.highway.construction.living_street" = "Rakenteilla oleva tie"; +"type.highway.construction.road" = "Rakenteilla oleva tie"; +"type.highway.construction.track" = "Rakenteilla oleva tie"; "type.highway.cycleway" = "Pyörätie"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Silta"; diff --git a/iphone/Maps/LocalizedStrings/fr.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/fr.lproj/Localizable.strings index 9fbbd8d68..37897cb5d 100644 --- a/iphone/Maps/LocalizedStrings/fr.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/fr.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Oui"; /* E.g. "WiFi:No" */ "no_available" = "Non"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacité : %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Réseau : %@"; "trip_finished" = "Vous êtes arrivé(e) !"; diff --git a/iphone/Maps/LocalizedStrings/fr.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/fr.lproj/LocalizableTypes.strings index 60a9561d2..e48d3c740 100644 --- a/iphone/Maps/LocalizedStrings/fr.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/fr.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunnel"; "type.highway.bus_stop" = "Arrêt de bus"; "type.highway.construction" = "Route en construction"; +"type.highway.construction.motorway" = "Route en construction"; +"type.highway.construction.motorway_link" = "Route en construction"; +"type.highway.construction.trunk" = "Route en construction"; +"type.highway.construction.trunk_link" = "Route en construction"; +"type.highway.construction.primary" = "Route en construction"; +"type.highway.construction.primary_link" = "Route en construction"; +"type.highway.construction.secondary" = "Route en construction"; +"type.highway.construction.secondary_link" = "Route en construction"; +"type.highway.construction.tertiary" = "Route en construction"; +"type.highway.construction.tertiary_link" = "Route en construction"; +"type.highway.construction.residential" = "Route en construction"; +"type.highway.construction.unclassified" = "Route en construction"; +"type.highway.construction.service" = "Route en construction"; +"type.highway.construction.living_street" = "Route en construction"; +"type.highway.construction.road" = "Route en construction"; +"type.highway.construction.track" = "Route en construction"; "type.highway.cycleway" = "Piste cyclable"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Pont"; @@ -694,6 +710,7 @@ "type.landuse.plant_nursery" = "Pépinière"; "type.leisure" = "Loisir"; "type.leisure.bandstand" = "Kiosque à musique"; +"type.amenity.stage" = "Scène"; "type.leisure.common" = "Terrain public"; "type.leisure.dog_park" = "Parc canin"; "type.leisure.escape_game" = "Escape room"; diff --git a/iphone/Maps/LocalizedStrings/gl.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/gl.lproj/LocalizableTypes.strings index 997243f63..be0b960f7 100644 --- a/iphone/Maps/LocalizedStrings/gl.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/gl.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Túnel"; "type.highway.bus_stop" = "Parada de autobús"; "type.highway.construction" = "Vía en construción"; +"type.highway.construction.motorway" = "Vía en construción"; +"type.highway.construction.motorway_link" = "Vía en construción"; +"type.highway.construction.trunk" = "Vía en construción"; +"type.highway.construction.trunk_link" = "Vía en construción"; +"type.highway.construction.primary" = "Vía en construción"; +"type.highway.construction.primary_link" = "Vía en construción"; +"type.highway.construction.secondary" = "Vía en construción"; +"type.highway.construction.secondary_link" = "Vía en construción"; +"type.highway.construction.tertiary" = "Vía en construción"; +"type.highway.construction.tertiary_link" = "Vía en construción"; +"type.highway.construction.residential" = "Vía en construción"; +"type.highway.construction.unclassified" = "Vía en construción"; +"type.highway.construction.service" = "Vía en construción"; +"type.highway.construction.living_street" = "Vía en construción"; +"type.highway.construction.road" = "Vía en construción"; +"type.highway.construction.track" = "Vía en construción"; "type.highway.cycleway" = "Ciclovía"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Puente"; diff --git a/iphone/Maps/LocalizedStrings/gsw.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/gsw.lproj/LocalizableTypes.strings index a5485eec2..016a369ec 100644 --- a/iphone/Maps/LocalizedStrings/gsw.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/gsw.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunnel"; "type.highway.bus_stop" = "Bushaltistell"; "type.highway.construction" = "Strass im Bau"; +"type.highway.construction.motorway" = "Strass im Bau"; +"type.highway.construction.motorway_link" = "Strass im Bau"; +"type.highway.construction.trunk" = "Strass im Bau"; +"type.highway.construction.trunk_link" = "Strass im Bau"; +"type.highway.construction.primary" = "Strass im Bau"; +"type.highway.construction.primary_link" = "Strass im Bau"; +"type.highway.construction.secondary" = "Strass im Bau"; +"type.highway.construction.secondary_link" = "Strass im Bau"; +"type.highway.construction.tertiary" = "Strass im Bau"; +"type.highway.construction.tertiary_link" = "Strass im Bau"; +"type.highway.construction.residential" = "Strass im Bau"; +"type.highway.construction.unclassified" = "Strass im Bau"; +"type.highway.construction.service" = "Strass im Bau"; +"type.highway.construction.living_street" = "Strass im Bau"; +"type.highway.construction.road" = "Strass im Bau"; +"type.highway.construction.track" = "Strass im Bau"; "type.highway.cycleway" = "Veloweg"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Brugg"; diff --git a/iphone/Maps/LocalizedStrings/he.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/he.lproj/Localizable.strings index c013d2834..9c683f4f4 100644 --- a/iphone/Maps/LocalizedStrings/he.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/he.lproj/Localizable.strings @@ -673,8 +673,6 @@ "yes_available" = "כן"; /* E.g. "WiFi:No" */ "no_available" = "לא"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "קיבולת: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "רשת: %@"; "trip_finished" = "הגעת!"; diff --git a/iphone/Maps/LocalizedStrings/he.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/he.lproj/LocalizableTypes.strings index a328e3dff..87580519d 100644 --- a/iphone/Maps/LocalizedStrings/he.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/he.lproj/LocalizableTypes.strings @@ -448,6 +448,22 @@ "type.highway.busway.tunnel" = "מִנהָרָה"; "type.highway.bus_stop" = "תחנת אוטובוס"; "type.highway.construction" = "כביש בבניה"; +"type.highway.construction.motorway" = "כביש בבניה"; +"type.highway.construction.motorway_link" = "כביש בבניה"; +"type.highway.construction.trunk" = "כביש בבניה"; +"type.highway.construction.trunk_link" = "כביש בבניה"; +"type.highway.construction.primary" = "כביש בבניה"; +"type.highway.construction.primary_link" = "כביש בבניה"; +"type.highway.construction.secondary" = "כביש בבניה"; +"type.highway.construction.secondary_link" = "כביש בבניה"; +"type.highway.construction.tertiary" = "כביש בבניה"; +"type.highway.construction.tertiary_link" = "כביש בבניה"; +"type.highway.construction.residential" = "כביש בבניה"; +"type.highway.construction.unclassified" = "כביש בבניה"; +"type.highway.construction.service" = "כביש בבניה"; +"type.highway.construction.living_street" = "כביש בבניה"; +"type.highway.construction.road" = "כביש בבניה"; +"type.highway.construction.track" = "כביש בבניה"; "type.highway.cycleway" = "שביל אופניים"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "גשר לאופניים"; diff --git a/iphone/Maps/LocalizedStrings/hi.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/hi.lproj/Localizable.strings index 9264eddfc..03338000a 100644 --- a/iphone/Maps/LocalizedStrings/hi.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/hi.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "हॉं"; /* E.g. "WiFi:No" */ "no_available" = "नहीं"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "क्षमता: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "नेटवर्क: %@"; "trip_finished" = "You have arrived!"; diff --git a/iphone/Maps/LocalizedStrings/hi.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/hi.lproj/LocalizableTypes.strings index 78477b142..f943befaf 100644 --- a/iphone/Maps/LocalizedStrings/hi.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/hi.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunnel"; "type.highway.bus_stop" = "बस स्टॉप"; "type.highway.construction" = "निर्माणाधीन सड़क"; +"type.highway.construction.motorway" = "निर्माणाधीन सड़क"; +"type.highway.construction.motorway_link" = "निर्माणाधीन सड़क"; +"type.highway.construction.trunk" = "निर्माणाधीन सड़क"; +"type.highway.construction.trunk_link" = "निर्माणाधीन सड़क"; +"type.highway.construction.primary" = "निर्माणाधीन सड़क"; +"type.highway.construction.primary_link" = "निर्माणाधीन सड़क"; +"type.highway.construction.secondary" = "निर्माणाधीन सड़क"; +"type.highway.construction.secondary_link" = "निर्माणाधीन सड़क"; +"type.highway.construction.tertiary" = "निर्माणाधीन सड़क"; +"type.highway.construction.tertiary_link" = "निर्माणाधीन सड़क"; +"type.highway.construction.residential" = "निर्माणाधीन सड़क"; +"type.highway.construction.unclassified" = "निर्माणाधीन सड़क"; +"type.highway.construction.service" = "निर्माणाधीन सड़क"; +"type.highway.construction.living_street" = "निर्माणाधीन सड़क"; +"type.highway.construction.road" = "निर्माणाधीन सड़क"; +"type.highway.construction.track" = "निर्माणाधीन सड़क"; "type.highway.cycleway" = "साइकिल मार्ग"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Bridge"; diff --git a/iphone/Maps/LocalizedStrings/hu.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/hu.lproj/Localizable.strings index b5afd92c1..d98538d92 100644 --- a/iphone/Maps/LocalizedStrings/hu.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/hu.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Igen"; /* E.g. "WiFi:No" */ "no_available" = "Nem"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapacitás: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Hálózat: %@"; "trip_finished" = "Megérkezett!"; diff --git a/iphone/Maps/LocalizedStrings/hu.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/hu.lproj/LocalizableTypes.strings index ae232f6ee..01228eba0 100644 --- a/iphone/Maps/LocalizedStrings/hu.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/hu.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Alagút"; "type.highway.bus_stop" = "Buszmegálló"; "type.highway.construction" = "Útépítés"; +"type.highway.construction.motorway" = "Útépítés"; +"type.highway.construction.motorway_link" = "Útépítés"; +"type.highway.construction.trunk" = "Útépítés"; +"type.highway.construction.trunk_link" = "Útépítés"; +"type.highway.construction.primary" = "Útépítés"; +"type.highway.construction.primary_link" = "Útépítés"; +"type.highway.construction.secondary" = "Útépítés"; +"type.highway.construction.secondary_link" = "Útépítés"; +"type.highway.construction.tertiary" = "Útépítés"; +"type.highway.construction.tertiary_link" = "Útépítés"; +"type.highway.construction.residential" = "Útépítés"; +"type.highway.construction.unclassified" = "Útépítés"; +"type.highway.construction.service" = "Útépítés"; +"type.highway.construction.living_street" = "Útépítés"; +"type.highway.construction.road" = "Útépítés"; +"type.highway.construction.track" = "Útépítés"; "type.highway.cycleway" = "Kerékpárút"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Híd"; diff --git a/iphone/Maps/LocalizedStrings/id.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/id.lproj/Localizable.strings index fffa5010e..1863ebdc8 100644 --- a/iphone/Maps/LocalizedStrings/id.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/id.lproj/Localizable.strings @@ -679,8 +679,6 @@ "yes_available" = "Ya"; /* E.g. "WiFi:No" */ "no_available" = "Tidak"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapasitas: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Jaringan: %@"; "trip_finished" = "Anda telah sampai!"; diff --git a/iphone/Maps/LocalizedStrings/id.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/id.lproj/LocalizableTypes.strings index d8e10b31d..36b85543e 100644 --- a/iphone/Maps/LocalizedStrings/id.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/id.lproj/LocalizableTypes.strings @@ -430,6 +430,22 @@ "type.highway.busway.tunnel" = "Terowongan"; "type.highway.bus_stop" = "Halte bus"; "type.highway.construction" = "Jalan sedang dibangun"; +"type.highway.construction.motorway" = "Jalan sedang dibangun"; +"type.highway.construction.motorway_link" = "Jalan sedang dibangun"; +"type.highway.construction.trunk" = "Jalan sedang dibangun"; +"type.highway.construction.trunk_link" = "Jalan sedang dibangun"; +"type.highway.construction.primary" = "Jalan sedang dibangun"; +"type.highway.construction.primary_link" = "Jalan sedang dibangun"; +"type.highway.construction.secondary" = "Jalan sedang dibangun"; +"type.highway.construction.secondary_link" = "Jalan sedang dibangun"; +"type.highway.construction.tertiary" = "Jalan sedang dibangun"; +"type.highway.construction.tertiary_link" = "Jalan sedang dibangun"; +"type.highway.construction.residential" = "Jalan sedang dibangun"; +"type.highway.construction.unclassified" = "Jalan sedang dibangun"; +"type.highway.construction.service" = "Jalan sedang dibangun"; +"type.highway.construction.living_street" = "Jalan sedang dibangun"; +"type.highway.construction.road" = "Jalan sedang dibangun"; +"type.highway.construction.track" = "Jalan sedang dibangun"; "type.highway.cycleway" = "Jalur Sepeda"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Menjembatani"; diff --git a/iphone/Maps/LocalizedStrings/is.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/is.lproj/LocalizableTypes.strings index 5da574e46..1f86e9984 100644 --- a/iphone/Maps/LocalizedStrings/is.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/is.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Göng"; "type.highway.bus_stop" = "Strætisvagnabiðstöð"; "type.highway.construction" = "Vegur í byggingu"; +"type.highway.construction.motorway" = "Vegur í byggingu"; +"type.highway.construction.motorway_link" = "Vegur í byggingu"; +"type.highway.construction.trunk" = "Vegur í byggingu"; +"type.highway.construction.trunk_link" = "Vegur í byggingu"; +"type.highway.construction.primary" = "Vegur í byggingu"; +"type.highway.construction.primary_link" = "Vegur í byggingu"; +"type.highway.construction.secondary" = "Vegur í byggingu"; +"type.highway.construction.secondary_link" = "Vegur í byggingu"; +"type.highway.construction.tertiary" = "Vegur í byggingu"; +"type.highway.construction.tertiary_link" = "Vegur í byggingu"; +"type.highway.construction.residential" = "Vegur í byggingu"; +"type.highway.construction.unclassified" = "Vegur í byggingu"; +"type.highway.construction.service" = "Vegur í byggingu"; +"type.highway.construction.living_street" = "Vegur í byggingu"; +"type.highway.construction.road" = "Vegur í byggingu"; +"type.highway.construction.track" = "Vegur í byggingu"; "type.highway.cycleway" = "Hjólastígur"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Brú"; diff --git a/iphone/Maps/LocalizedStrings/it.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/it.lproj/Localizable.strings index f46b7d4b3..0645f97d3 100644 --- a/iphone/Maps/LocalizedStrings/it.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/it.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Sì"; /* E.g. "WiFi:No" */ "no_available" = "No"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacità: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Rete: %@"; "trip_finished" = "Sei arrivato!"; diff --git a/iphone/Maps/LocalizedStrings/it.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/it.lproj/LocalizableTypes.strings index 6106fe752..f52aaf6f6 100644 --- a/iphone/Maps/LocalizedStrings/it.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/it.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Galleria"; "type.highway.bus_stop" = "Fermata dell'autobus"; "type.highway.construction" = "Strada in costruzione"; +"type.highway.construction.motorway" = "Strada in costruzione"; +"type.highway.construction.motorway_link" = "Strada in costruzione"; +"type.highway.construction.trunk" = "Strada in costruzione"; +"type.highway.construction.trunk_link" = "Strada in costruzione"; +"type.highway.construction.primary" = "Strada in costruzione"; +"type.highway.construction.primary_link" = "Strada in costruzione"; +"type.highway.construction.secondary" = "Strada in costruzione"; +"type.highway.construction.secondary_link" = "Strada in costruzione"; +"type.highway.construction.tertiary" = "Strada in costruzione"; +"type.highway.construction.tertiary_link" = "Strada in costruzione"; +"type.highway.construction.residential" = "Strada in costruzione"; +"type.highway.construction.unclassified" = "Strada in costruzione"; +"type.highway.construction.service" = "Strada in costruzione"; +"type.highway.construction.living_street" = "Strada in costruzione"; +"type.highway.construction.road" = "Strada in costruzione"; +"type.highway.construction.track" = "Strada in costruzione"; "type.highway.cycleway" = "Pista ciclabile"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Ponte"; diff --git a/iphone/Maps/LocalizedStrings/ja.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ja.lproj/Localizable.strings index a3441487e..7602b272b 100644 --- a/iphone/Maps/LocalizedStrings/ja.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ja.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "はい"; /* E.g. "WiFi:No" */ "no_available" = "いいえ"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "定員:%@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "ネットワーク: %@"; "trip_finished" = "到着しました!"; diff --git a/iphone/Maps/LocalizedStrings/ja.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/ja.lproj/LocalizableTypes.strings index ea1d539d9..888a54fb6 100644 --- a/iphone/Maps/LocalizedStrings/ja.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/ja.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "トンネル"; "type.highway.bus_stop" = "バス停"; "type.highway.construction" = "工事中の道路"; +"type.highway.construction.motorway" = "工事中の道路"; +"type.highway.construction.motorway_link" = "工事中の道路"; +"type.highway.construction.trunk" = "工事中の道路"; +"type.highway.construction.trunk_link" = "工事中の道路"; +"type.highway.construction.primary" = "工事中の道路"; +"type.highway.construction.primary_link" = "工事中の道路"; +"type.highway.construction.secondary" = "工事中の道路"; +"type.highway.construction.secondary_link" = "工事中の道路"; +"type.highway.construction.tertiary" = "工事中の道路"; +"type.highway.construction.tertiary_link" = "工事中の道路"; +"type.highway.construction.residential" = "工事中の道路"; +"type.highway.construction.unclassified" = "工事中の道路"; +"type.highway.construction.service" = "工事中の道路"; +"type.highway.construction.living_street" = "工事中の道路"; +"type.highway.construction.road" = "工事中の道路"; +"type.highway.construction.track" = "工事中の道路"; "type.highway.cycleway" = "自転車道"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "自転車道(橋)"; diff --git a/iphone/Maps/LocalizedStrings/ko.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ko.lproj/Localizable.strings index fbb200f1f..ce8f2b53c 100644 --- a/iphone/Maps/LocalizedStrings/ko.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ko.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "네"; /* E.g. "WiFi:No" */ "no_available" = "아니오"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "수용 인원: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "네트워크: %@"; "trip_finished" = "도착했습니다!"; diff --git a/iphone/Maps/LocalizedStrings/ko.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/ko.lproj/LocalizableTypes.strings index d5a276355..ffadacfaa 100644 --- a/iphone/Maps/LocalizedStrings/ko.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/ko.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "터널"; "type.highway.bus_stop" = "버스 정류장"; "type.highway.construction" = "공사 중 도로"; +"type.highway.construction.motorway" = "공사 중 도로"; +"type.highway.construction.motorway_link" = "공사 중 도로"; +"type.highway.construction.trunk" = "공사 중 도로"; +"type.highway.construction.trunk_link" = "공사 중 도로"; +"type.highway.construction.primary" = "공사 중 도로"; +"type.highway.construction.primary_link" = "공사 중 도로"; +"type.highway.construction.secondary" = "공사 중 도로"; +"type.highway.construction.secondary_link" = "공사 중 도로"; +"type.highway.construction.tertiary" = "공사 중 도로"; +"type.highway.construction.tertiary_link" = "공사 중 도로"; +"type.highway.construction.residential" = "공사 중 도로"; +"type.highway.construction.unclassified" = "공사 중 도로"; +"type.highway.construction.service" = "공사 중 도로"; +"type.highway.construction.living_street" = "공사 중 도로"; +"type.highway.construction.road" = "공사 중 도로"; +"type.highway.construction.track" = "공사 중 도로"; "type.highway.cycleway" = "Cycle Path"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "다리"; diff --git a/iphone/Maps/LocalizedStrings/lt.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/lt.lproj/Localizable.strings index 4e9a2eabe..03c1ecc12 100644 --- a/iphone/Maps/LocalizedStrings/lt.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/lt.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Taip"; /* E.g. "WiFi:No" */ "no_available" = "Ne"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Talpa: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Tinklas: %@"; "trip_finished" = "Jūs pasiekėte kelionės tikslą!"; diff --git a/iphone/Maps/LocalizedStrings/lt.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/lt.lproj/LocalizableTypes.strings index 16fa86676..e994ff793 100644 --- a/iphone/Maps/LocalizedStrings/lt.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/lt.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunelis"; "type.highway.bus_stop" = "Stotelė"; "type.highway.construction" = "Tiesiamas kelias"; +"type.highway.construction.motorway" = "Tiesiamas kelias"; +"type.highway.construction.motorway_link" = "Tiesiamas kelias"; +"type.highway.construction.trunk" = "Tiesiamas kelias"; +"type.highway.construction.trunk_link" = "Tiesiamas kelias"; +"type.highway.construction.primary" = "Tiesiamas kelias"; +"type.highway.construction.primary_link" = "Tiesiamas kelias"; +"type.highway.construction.secondary" = "Tiesiamas kelias"; +"type.highway.construction.secondary_link" = "Tiesiamas kelias"; +"type.highway.construction.tertiary" = "Tiesiamas kelias"; +"type.highway.construction.tertiary_link" = "Tiesiamas kelias"; +"type.highway.construction.residential" = "Tiesiamas kelias"; +"type.highway.construction.unclassified" = "Tiesiamas kelias"; +"type.highway.construction.service" = "Tiesiamas kelias"; +"type.highway.construction.living_street" = "Tiesiamas kelias"; +"type.highway.construction.road" = "Tiesiamas kelias"; +"type.highway.construction.track" = "Tiesiamas kelias"; "type.highway.cycleway" = "Dviračių takas"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Tiltas"; diff --git a/iphone/Maps/LocalizedStrings/lv.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/lv.lproj/Localizable.strings index 217be0148..0f0d621d9 100644 --- a/iphone/Maps/LocalizedStrings/lv.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/lv.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Pieejams"; /* E.g. "WiFi:No" */ "no_available" = "Nav pieejams"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Ietilpība: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Tīkls: %@"; "trip_finished" = "Ieradāties galamērķī!"; diff --git a/iphone/Maps/LocalizedStrings/mr.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/mr.lproj/Localizable.strings index ec9da331e..a5d478280 100644 --- a/iphone/Maps/LocalizedStrings/mr.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/mr.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "होय"; /* E.g. "WiFi:No" */ "no_available" = "नाही"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "क्षमता: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "नेटवर्क: %@"; "trip_finished" = "तुम्ही पोचलात!"; diff --git a/iphone/Maps/LocalizedStrings/mr.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/mr.lproj/LocalizableTypes.strings index fb72b39d6..fc9136b0e 100644 --- a/iphone/Maps/LocalizedStrings/mr.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/mr.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "बोगदा"; "type.highway.bus_stop" = "बस थांबा"; "type.highway.construction" = "बांधकामाधीन रस्ता"; +"type.highway.construction.motorway" = "बांधकामाधीन रस्ता"; +"type.highway.construction.motorway_link" = "बांधकामाधीन रस्ता"; +"type.highway.construction.trunk" = "बांधकामाधीन रस्ता"; +"type.highway.construction.trunk_link" = "बांधकामाधीन रस्ता"; +"type.highway.construction.primary" = "बांधकामाधीन रस्ता"; +"type.highway.construction.primary_link" = "बांधकामाधीन रस्ता"; +"type.highway.construction.secondary" = "बांधकामाधीन रस्ता"; +"type.highway.construction.secondary_link" = "बांधकामाधीन रस्ता"; +"type.highway.construction.tertiary" = "बांधकामाधीन रस्ता"; +"type.highway.construction.tertiary_link" = "बांधकामाधीन रस्ता"; +"type.highway.construction.residential" = "बांधकामाधीन रस्ता"; +"type.highway.construction.unclassified" = "बांधकामाधीन रस्ता"; +"type.highway.construction.service" = "बांधकामाधीन रस्ता"; +"type.highway.construction.living_street" = "बांधकामाधीन रस्ता"; +"type.highway.construction.road" = "बांधकामाधीन रस्ता"; +"type.highway.construction.track" = "बांधकामाधीन रस्ता"; "type.highway.cycleway" = "सायकल वाट"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "पूल"; diff --git a/iphone/Maps/LocalizedStrings/mt.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/mt.lproj/Localizable.strings index 9489db2a2..54ffed6d3 100644 --- a/iphone/Maps/LocalizedStrings/mt.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/mt.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Iva"; /* E.g. "WiFi:No" */ "no_available" = "Le"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacity: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Network: %@"; "trip_finished" = "Wasalt!"; diff --git a/iphone/Maps/LocalizedStrings/nb.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/nb.lproj/Localizable.strings index c33d1dfd0..318c83669 100644 --- a/iphone/Maps/LocalizedStrings/nb.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/nb.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Ja"; /* E.g. "WiFi:No" */ "no_available" = "Nei"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapasitet: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Nettverk: %@"; "trip_finished" = "Du har ankommet!"; diff --git a/iphone/Maps/LocalizedStrings/nb.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/nb.lproj/LocalizableTypes.strings index 8b64e7d90..2bd154436 100644 --- a/iphone/Maps/LocalizedStrings/nb.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/nb.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunnel"; "type.highway.bus_stop" = "Busstopp"; "type.highway.construction" = "Veikonstruksjon"; +"type.highway.construction.motorway" = "Veikonstruksjon"; +"type.highway.construction.motorway_link" = "Veikonstruksjon"; +"type.highway.construction.trunk" = "Veikonstruksjon"; +"type.highway.construction.trunk_link" = "Veikonstruksjon"; +"type.highway.construction.primary" = "Veikonstruksjon"; +"type.highway.construction.primary_link" = "Veikonstruksjon"; +"type.highway.construction.secondary" = "Veikonstruksjon"; +"type.highway.construction.secondary_link" = "Veikonstruksjon"; +"type.highway.construction.tertiary" = "Veikonstruksjon"; +"type.highway.construction.tertiary_link" = "Veikonstruksjon"; +"type.highway.construction.residential" = "Veikonstruksjon"; +"type.highway.construction.unclassified" = "Veikonstruksjon"; +"type.highway.construction.service" = "Veikonstruksjon"; +"type.highway.construction.living_street" = "Veikonstruksjon"; +"type.highway.construction.road" = "Veikonstruksjon"; +"type.highway.construction.track" = "Veikonstruksjon"; "type.highway.cycleway" = "Sykkelvei"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Bru"; diff --git a/iphone/Maps/LocalizedStrings/nl.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/nl.lproj/Localizable.strings index 1037ddc25..a637d52c4 100644 --- a/iphone/Maps/LocalizedStrings/nl.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/nl.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Ja"; /* E.g. "WiFi:No" */ "no_available" = "Nee"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capaciteit: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Netwerk: %@"; "trip_finished" = "Bestemming bereikt!"; diff --git a/iphone/Maps/LocalizedStrings/nl.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/nl.lproj/LocalizableTypes.strings index c5e440e82..b7f76c8b7 100644 --- a/iphone/Maps/LocalizedStrings/nl.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/nl.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunnel"; "type.highway.bus_stop" = "Bushalte"; "type.highway.construction" = "Weg in aanbouw"; +"type.highway.construction.motorway" = "Weg in aanbouw"; +"type.highway.construction.motorway_link" = "Weg in aanbouw"; +"type.highway.construction.trunk" = "Weg in aanbouw"; +"type.highway.construction.trunk_link" = "Weg in aanbouw"; +"type.highway.construction.primary" = "Weg in aanbouw"; +"type.highway.construction.primary_link" = "Weg in aanbouw"; +"type.highway.construction.secondary" = "Weg in aanbouw"; +"type.highway.construction.secondary_link" = "Weg in aanbouw"; +"type.highway.construction.tertiary" = "Weg in aanbouw"; +"type.highway.construction.tertiary_link" = "Weg in aanbouw"; +"type.highway.construction.residential" = "Weg in aanbouw"; +"type.highway.construction.unclassified" = "Weg in aanbouw"; +"type.highway.construction.service" = "Weg in aanbouw"; +"type.highway.construction.living_street" = "Weg in aanbouw"; +"type.highway.construction.road" = "Weg in aanbouw"; +"type.highway.construction.track" = "Weg in aanbouw"; "type.highway.cycleway" = "Fietspad"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Fietsbrug"; diff --git a/iphone/Maps/LocalizedStrings/pl.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/pl.lproj/Localizable.strings index 873a37897..06df23cb7 100644 --- a/iphone/Maps/LocalizedStrings/pl.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/pl.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Tak"; /* E.g. "WiFi:No" */ "no_available" = "Nie"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Pojemność: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Sieć: %@"; "trip_finished" = "Jesteś na miejscu!"; diff --git a/iphone/Maps/LocalizedStrings/pl.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/pl.lproj/LocalizableTypes.strings index 3f5effe26..fffcf7ef8 100644 --- a/iphone/Maps/LocalizedStrings/pl.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/pl.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunel"; "type.highway.bus_stop" = "Przystanek autobusowy"; "type.highway.construction" = "Droga w trakcie budowy"; +"type.highway.construction.motorway" = "Droga w trakcie budowy"; +"type.highway.construction.motorway_link" = "Droga w trakcie budowy"; +"type.highway.construction.trunk" = "Droga w trakcie budowy"; +"type.highway.construction.trunk_link" = "Droga w trakcie budowy"; +"type.highway.construction.primary" = "Droga w trakcie budowy"; +"type.highway.construction.primary_link" = "Droga w trakcie budowy"; +"type.highway.construction.secondary" = "Droga w trakcie budowy"; +"type.highway.construction.secondary_link" = "Droga w trakcie budowy"; +"type.highway.construction.tertiary" = "Droga w trakcie budowy"; +"type.highway.construction.tertiary_link" = "Droga w trakcie budowy"; +"type.highway.construction.residential" = "Droga w trakcie budowy"; +"type.highway.construction.unclassified" = "Droga w trakcie budowy"; +"type.highway.construction.service" = "Droga w trakcie budowy"; +"type.highway.construction.living_street" = "Droga w trakcie budowy"; +"type.highway.construction.road" = "Droga w trakcie budowy"; +"type.highway.construction.track" = "Droga w trakcie budowy"; "type.highway.cycleway" = "Droga rowerowa"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Most drogowy dla rowerów"; diff --git a/iphone/Maps/LocalizedStrings/pt-BR.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/pt-BR.lproj/Localizable.strings index f9ff5ed0c..641423c88 100644 --- a/iphone/Maps/LocalizedStrings/pt-BR.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/pt-BR.lproj/Localizable.strings @@ -688,8 +688,6 @@ "yes_available" = "Sim"; /* E.g. "WiFi:No" */ "no_available" = "Não"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacidade: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Rede: %@"; "trip_finished" = "Você chegou!"; diff --git a/iphone/Maps/LocalizedStrings/pt-BR.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/pt-BR.lproj/LocalizableTypes.strings index 1d94e053a..92273713b 100644 --- a/iphone/Maps/LocalizedStrings/pt-BR.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/pt-BR.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Túnel"; "type.highway.bus_stop" = "Ponto de ônibus"; "type.highway.construction" = "Via em construção"; +"type.highway.construction.motorway" = "Via em construção"; +"type.highway.construction.motorway_link" = "Via em construção"; +"type.highway.construction.trunk" = "Via em construção"; +"type.highway.construction.trunk_link" = "Via em construção"; +"type.highway.construction.primary" = "Via em construção"; +"type.highway.construction.primary_link" = "Via em construção"; +"type.highway.construction.secondary" = "Via em construção"; +"type.highway.construction.secondary_link" = "Via em construção"; +"type.highway.construction.tertiary" = "Via em construção"; +"type.highway.construction.tertiary_link" = "Via em construção"; +"type.highway.construction.residential" = "Via em construção"; +"type.highway.construction.unclassified" = "Via em construção"; +"type.highway.construction.service" = "Via em construção"; +"type.highway.construction.living_street" = "Via em construção"; +"type.highway.construction.road" = "Via em construção"; +"type.highway.construction.track" = "Via em construção"; "type.highway.cycleway" = "Ciclovia"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Ponte para ciclistas"; diff --git a/iphone/Maps/LocalizedStrings/pt.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/pt.lproj/Localizable.strings index fdb3600aa..ecfd8a880 100644 --- a/iphone/Maps/LocalizedStrings/pt.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/pt.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Sim"; /* E.g. "WiFi:No" */ "no_available" = "Não"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacidade: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Rede: %@"; "trip_finished" = "Chegou ao destino!"; diff --git a/iphone/Maps/LocalizedStrings/pt.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/pt.lproj/LocalizableTypes.strings index a016f4ab1..e6407bc5c 100644 --- a/iphone/Maps/LocalizedStrings/pt.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/pt.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Túnel"; "type.highway.bus_stop" = "Paragem de autocarros"; "type.highway.construction" = "Estrada em construção"; +"type.highway.construction.motorway" = "Estrada em construção"; +"type.highway.construction.motorway_link" = "Estrada em construção"; +"type.highway.construction.trunk" = "Estrada em construção"; +"type.highway.construction.trunk_link" = "Estrada em construção"; +"type.highway.construction.primary" = "Estrada em construção"; +"type.highway.construction.primary_link" = "Estrada em construção"; +"type.highway.construction.secondary" = "Estrada em construção"; +"type.highway.construction.secondary_link" = "Estrada em construção"; +"type.highway.construction.tertiary" = "Estrada em construção"; +"type.highway.construction.tertiary_link" = "Estrada em construção"; +"type.highway.construction.residential" = "Estrada em construção"; +"type.highway.construction.unclassified" = "Estrada em construção"; +"type.highway.construction.service" = "Estrada em construção"; +"type.highway.construction.living_street" = "Estrada em construção"; +"type.highway.construction.road" = "Estrada em construção"; +"type.highway.construction.track" = "Estrada em construção"; "type.highway.cycleway" = "Ciclovia"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Ponte"; diff --git a/iphone/Maps/LocalizedStrings/ro.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ro.lproj/Localizable.strings index c3dcf395a..6f73d8ed2 100644 --- a/iphone/Maps/LocalizedStrings/ro.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ro.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Da"; /* E.g. "WiFi:No" */ "no_available" = "Nu"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Capacitate: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Rețea: %@"; "trip_finished" = "Ai ajuns!"; diff --git a/iphone/Maps/LocalizedStrings/ro.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/ro.lproj/LocalizableTypes.strings index 4329cf755..1e046583b 100644 --- a/iphone/Maps/LocalizedStrings/ro.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/ro.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunel"; "type.highway.bus_stop" = "Stație de autobuz"; "type.highway.construction" = "Drum în construcție"; +"type.highway.construction.motorway" = "Drum în construcție"; +"type.highway.construction.motorway_link" = "Drum în construcție"; +"type.highway.construction.trunk" = "Drum în construcție"; +"type.highway.construction.trunk_link" = "Drum în construcție"; +"type.highway.construction.primary" = "Drum în construcție"; +"type.highway.construction.primary_link" = "Drum în construcție"; +"type.highway.construction.secondary" = "Drum în construcție"; +"type.highway.construction.secondary_link" = "Drum în construcție"; +"type.highway.construction.tertiary" = "Drum în construcție"; +"type.highway.construction.tertiary_link" = "Drum în construcție"; +"type.highway.construction.residential" = "Drum în construcție"; +"type.highway.construction.unclassified" = "Drum în construcție"; +"type.highway.construction.service" = "Drum în construcție"; +"type.highway.construction.living_street" = "Drum în construcție"; +"type.highway.construction.road" = "Drum în construcție"; +"type.highway.construction.track" = "Drum în construcție"; "type.highway.cycleway" = "Pistă de Biciclete"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Pod"; diff --git a/iphone/Maps/LocalizedStrings/ru.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/ru.lproj/Localizable.strings index ba21445cc..ac845c76c 100644 --- a/iphone/Maps/LocalizedStrings/ru.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/ru.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Есть"; /* E.g. "WiFi:No" */ "no_available" = "Нет"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Вместимость: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Сеть: %@"; "trip_finished" = "Вы прибыли!"; diff --git a/iphone/Maps/LocalizedStrings/ru.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/ru.lproj/LocalizableTypes.strings index 217981b72..dea54d33f 100644 --- a/iphone/Maps/LocalizedStrings/ru.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/ru.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Тоннель"; "type.highway.bus_stop" = "Остановка"; "type.highway.construction" = "Строящаяся дорога"; +"type.highway.construction.motorway" = "Строящаяся дорога"; +"type.highway.construction.motorway_link" = "Строящаяся дорога"; +"type.highway.construction.trunk" = "Строящаяся дорога"; +"type.highway.construction.trunk_link" = "Строящаяся дорога"; +"type.highway.construction.primary" = "Строящаяся дорога"; +"type.highway.construction.primary_link" = "Строящаяся дорога"; +"type.highway.construction.secondary" = "Строящаяся дорога"; +"type.highway.construction.secondary_link" = "Строящаяся дорога"; +"type.highway.construction.tertiary" = "Строящаяся дорога"; +"type.highway.construction.tertiary_link" = "Строящаяся дорога"; +"type.highway.construction.residential" = "Строящаяся дорога"; +"type.highway.construction.unclassified" = "Строящаяся дорога"; +"type.highway.construction.service" = "Строящаяся дорога"; +"type.highway.construction.living_street" = "Строящаяся дорога"; +"type.highway.construction.road" = "Строящаяся дорога"; +"type.highway.construction.track" = "Строящаяся дорога"; "type.highway.cycleway" = "Велодорожка"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Мост"; diff --git a/iphone/Maps/LocalizedStrings/sk.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/sk.lproj/Localizable.strings index 248738b81..0d4acbfa2 100644 --- a/iphone/Maps/LocalizedStrings/sk.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/sk.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Áno"; /* E.g. "WiFi:No" */ "no_available" = "Nie"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapacita: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Sieť: %@"; "trip_finished" = "Prišli ste do cieľa!"; diff --git a/iphone/Maps/LocalizedStrings/sk.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/sk.lproj/LocalizableTypes.strings index be537e420..a1fbc1c2a 100644 --- a/iphone/Maps/LocalizedStrings/sk.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/sk.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunel"; "type.highway.bus_stop" = "Autobusová zastávka"; "type.highway.construction" = "Cesta vo výstavbe"; +"type.highway.construction.motorway" = "Cesta vo výstavbe"; +"type.highway.construction.motorway_link" = "Cesta vo výstavbe"; +"type.highway.construction.trunk" = "Cesta vo výstavbe"; +"type.highway.construction.trunk_link" = "Cesta vo výstavbe"; +"type.highway.construction.primary" = "Cesta vo výstavbe"; +"type.highway.construction.primary_link" = "Cesta vo výstavbe"; +"type.highway.construction.secondary" = "Cesta vo výstavbe"; +"type.highway.construction.secondary_link" = "Cesta vo výstavbe"; +"type.highway.construction.tertiary" = "Cesta vo výstavbe"; +"type.highway.construction.tertiary_link" = "Cesta vo výstavbe"; +"type.highway.construction.residential" = "Cesta vo výstavbe"; +"type.highway.construction.unclassified" = "Cesta vo výstavbe"; +"type.highway.construction.service" = "Cesta vo výstavbe"; +"type.highway.construction.living_street" = "Cesta vo výstavbe"; +"type.highway.construction.road" = "Cesta vo výstavbe"; +"type.highway.construction.track" = "Cesta vo výstavbe"; "type.highway.cycleway" = "Cyklocesta"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Most"; diff --git a/iphone/Maps/LocalizedStrings/sl.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/sl.lproj/LocalizableTypes.strings index 345fc9987..8f25c578e 100644 --- a/iphone/Maps/LocalizedStrings/sl.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/sl.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Predor"; "type.highway.bus_stop" = "Avtobusno postajališče"; "type.highway.construction" = "Cesta v gradnji"; +"type.highway.construction.motorway" = "Cesta v gradnji"; +"type.highway.construction.motorway_link" = "Cesta v gradnji"; +"type.highway.construction.trunk" = "Cesta v gradnji"; +"type.highway.construction.trunk_link" = "Cesta v gradnji"; +"type.highway.construction.primary" = "Cesta v gradnji"; +"type.highway.construction.primary_link" = "Cesta v gradnji"; +"type.highway.construction.secondary" = "Cesta v gradnji"; +"type.highway.construction.secondary_link" = "Cesta v gradnji"; +"type.highway.construction.tertiary" = "Cesta v gradnji"; +"type.highway.construction.tertiary_link" = "Cesta v gradnji"; +"type.highway.construction.residential" = "Cesta v gradnji"; +"type.highway.construction.unclassified" = "Cesta v gradnji"; +"type.highway.construction.service" = "Cesta v gradnji"; +"type.highway.construction.living_street" = "Cesta v gradnji"; +"type.highway.construction.road" = "Cesta v gradnji"; +"type.highway.construction.track" = "Cesta v gradnji"; "type.highway.cycleway" = "Kolesarska steza"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Most"; diff --git a/iphone/Maps/LocalizedStrings/sr.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/sr.lproj/Localizable.strings index cca6c3dbf..eb513014d 100644 --- a/iphone/Maps/LocalizedStrings/sr.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/sr.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Да"; /* E.g. "WiFi:No" */ "no_available" = "Не"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Број места: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Мрежа: %@"; "trip_finished" = "Стигли сте!"; diff --git a/iphone/Maps/LocalizedStrings/sr.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/sr.lproj/LocalizableTypes.strings index a1a1d7f36..944784c98 100644 --- a/iphone/Maps/LocalizedStrings/sr.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/sr.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Тунел"; "type.highway.bus_stop" = "Аутобуско стајалиште"; "type.highway.construction" = "Пут у изградњи"; +"type.highway.construction.motorway" = "Пут у изградњи"; +"type.highway.construction.motorway_link" = "Пут у изградњи"; +"type.highway.construction.trunk" = "Пут у изградњи"; +"type.highway.construction.trunk_link" = "Пут у изградњи"; +"type.highway.construction.primary" = "Пут у изградњи"; +"type.highway.construction.primary_link" = "Пут у изградњи"; +"type.highway.construction.secondary" = "Пут у изградњи"; +"type.highway.construction.secondary_link" = "Пут у изградњи"; +"type.highway.construction.tertiary" = "Пут у изградњи"; +"type.highway.construction.tertiary_link" = "Пут у изградњи"; +"type.highway.construction.residential" = "Пут у изградњи"; +"type.highway.construction.unclassified" = "Пут у изградњи"; +"type.highway.construction.service" = "Пут у изградњи"; +"type.highway.construction.living_street" = "Пут у изградњи"; +"type.highway.construction.road" = "Пут у изградњи"; +"type.highway.construction.track" = "Пут у изградњи"; "type.highway.cycleway" = "Бициклистичка стаза"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Мост"; diff --git a/iphone/Maps/LocalizedStrings/sv.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/sv.lproj/Localizable.strings index 6da513fdd..a86b01ef6 100644 --- a/iphone/Maps/LocalizedStrings/sv.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/sv.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Ja"; /* E.g. "WiFi:No" */ "no_available" = "Nej"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapacitet: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Nätverk: %@"; "trip_finished" = "Du är framme!"; diff --git a/iphone/Maps/LocalizedStrings/sv.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/sv.lproj/LocalizableTypes.strings index 84f8c105e..e55aed793 100644 --- a/iphone/Maps/LocalizedStrings/sv.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/sv.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tunnel"; "type.highway.bus_stop" = "Busshållplats"; "type.highway.construction" = "Väg under uppförande"; +"type.highway.construction.motorway" = "Väg under uppförande"; +"type.highway.construction.motorway_link" = "Väg under uppförande"; +"type.highway.construction.trunk" = "Väg under uppförande"; +"type.highway.construction.trunk_link" = "Väg under uppförande"; +"type.highway.construction.primary" = "Väg under uppförande"; +"type.highway.construction.primary_link" = "Väg under uppförande"; +"type.highway.construction.secondary" = "Väg under uppförande"; +"type.highway.construction.secondary_link" = "Väg under uppförande"; +"type.highway.construction.tertiary" = "Väg under uppförande"; +"type.highway.construction.tertiary_link" = "Väg under uppförande"; +"type.highway.construction.residential" = "Väg under uppförande"; +"type.highway.construction.unclassified" = "Väg under uppförande"; +"type.highway.construction.service" = "Väg under uppförande"; +"type.highway.construction.living_street" = "Väg under uppförande"; +"type.highway.construction.road" = "Väg under uppförande"; +"type.highway.construction.track" = "Väg under uppförande"; "type.highway.cycleway" = "Cykelbana"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Cykelbro"; diff --git a/iphone/Maps/LocalizedStrings/sw.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/sw.lproj/Localizable.strings index be1b16712..2810cc782 100644 --- a/iphone/Maps/LocalizedStrings/sw.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/sw.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Ndio"; /* E.g. "WiFi:No" */ "no_available" = "Hapana"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Uwezo: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Mtandao: %@"; "trip_finished" = "Umefika!"; diff --git a/iphone/Maps/LocalizedStrings/sw.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/sw.lproj/LocalizableTypes.strings index d713e8ce9..a8866d648 100644 --- a/iphone/Maps/LocalizedStrings/sw.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/sw.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Mtaro"; "type.highway.bus_stop" = "Bus Stop"; "type.highway.construction" = "Barabara inatengenezwa"; +"type.highway.construction.motorway" = "Barabara inatengenezwa"; +"type.highway.construction.motorway_link" = "Barabara inatengenezwa"; +"type.highway.construction.trunk" = "Barabara inatengenezwa"; +"type.highway.construction.trunk_link" = "Barabara inatengenezwa"; +"type.highway.construction.primary" = "Barabara inatengenezwa"; +"type.highway.construction.primary_link" = "Barabara inatengenezwa"; +"type.highway.construction.secondary" = "Barabara inatengenezwa"; +"type.highway.construction.secondary_link" = "Barabara inatengenezwa"; +"type.highway.construction.tertiary" = "Barabara inatengenezwa"; +"type.highway.construction.tertiary_link" = "Barabara inatengenezwa"; +"type.highway.construction.residential" = "Barabara inatengenezwa"; +"type.highway.construction.unclassified" = "Barabara inatengenezwa"; +"type.highway.construction.service" = "Barabara inatengenezwa"; +"type.highway.construction.living_street" = "Barabara inatengenezwa"; +"type.highway.construction.road" = "Barabara inatengenezwa"; +"type.highway.construction.track" = "Barabara inatengenezwa"; "type.highway.cycleway" = "Cycle Path"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Daraja"; diff --git a/iphone/Maps/LocalizedStrings/ta.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/ta.lproj/LocalizableTypes.strings index de67ffef7..877fb95e1 100644 --- a/iphone/Maps/LocalizedStrings/ta.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/ta.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "சுரங்கப்பாதை"; "type.highway.bus_stop" = "பேருந்து நிறுத்தம்"; "type.highway.construction" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.motorway" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.motorway_link" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.trunk" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.trunk_link" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.primary" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.primary_link" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.secondary" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.secondary_link" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.tertiary" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.tertiary_link" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.residential" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.unclassified" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.service" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.living_street" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.road" = "சாலை கட்டுமானத்தில் உள்ளது"; +"type.highway.construction.track" = "சாலை கட்டுமானத்தில் உள்ளது"; "type.highway.cycleway" = "சைக்கிள் பாதை"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "பாலம்"; diff --git a/iphone/Maps/LocalizedStrings/th.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/th.lproj/Localizable.strings index 5f40b1f4b..320288df3 100644 --- a/iphone/Maps/LocalizedStrings/th.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/th.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "ใช่"; /* E.g. "WiFi:No" */ "no_available" = "ไม่ใช่"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "ความจุ: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "เครือข่าย: %@"; "trip_finished" = "คุณมาถึงแล้ว!"; diff --git a/iphone/Maps/LocalizedStrings/th.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/th.lproj/LocalizableTypes.strings index 4e1c9e6a5..8edea2256 100644 --- a/iphone/Maps/LocalizedStrings/th.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/th.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "อุโมงค์"; "type.highway.bus_stop" = "ป้ายรถเมล์"; "type.highway.construction" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.motorway" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.motorway_link" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.trunk" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.trunk_link" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.primary" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.primary_link" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.secondary" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.secondary_link" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.tertiary" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.tertiary_link" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.residential" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.unclassified" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.service" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.living_street" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.road" = "ทางกำลังอยู่ในการก่อสร้าง"; +"type.highway.construction.track" = "ทางกำลังอยู่ในการก่อสร้าง"; "type.highway.cycleway" = "Cycle Path"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "สะพาน"; diff --git a/iphone/Maps/LocalizedStrings/tr.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/tr.lproj/Localizable.strings index cd47a902e..6cead9885 100644 --- a/iphone/Maps/LocalizedStrings/tr.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/tr.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Var"; /* E.g. "WiFi:No" */ "no_available" = "Yok"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Kapasite: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Ağ: %@"; "trip_finished" = "Vardınız!"; diff --git a/iphone/Maps/LocalizedStrings/tr.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/tr.lproj/LocalizableTypes.strings index 06c50ce1c..3f451f099 100644 --- a/iphone/Maps/LocalizedStrings/tr.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/tr.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Tünel"; "type.highway.bus_stop" = "Otobüs Durağı"; "type.highway.construction" = "Yapım Aşamasında Yol"; +"type.highway.construction.motorway" = "Yapım Aşamasında Yol"; +"type.highway.construction.motorway_link" = "Yapım Aşamasında Yol"; +"type.highway.construction.trunk" = "Yapım Aşamasında Yol"; +"type.highway.construction.trunk_link" = "Yapım Aşamasında Yol"; +"type.highway.construction.primary" = "Yapım Aşamasında Yol"; +"type.highway.construction.primary_link" = "Yapım Aşamasında Yol"; +"type.highway.construction.secondary" = "Yapım Aşamasında Yol"; +"type.highway.construction.secondary_link" = "Yapım Aşamasında Yol"; +"type.highway.construction.tertiary" = "Yapım Aşamasında Yol"; +"type.highway.construction.tertiary_link" = "Yapım Aşamasında Yol"; +"type.highway.construction.residential" = "Yapım Aşamasında Yol"; +"type.highway.construction.unclassified" = "Yapım Aşamasında Yol"; +"type.highway.construction.service" = "Yapım Aşamasında Yol"; +"type.highway.construction.living_street" = "Yapım Aşamasında Yol"; +"type.highway.construction.road" = "Yapım Aşamasında Yol"; +"type.highway.construction.track" = "Yapım Aşamasında Yol"; "type.highway.cycleway" = "Bisiklet Yolu"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Köprü"; diff --git a/iphone/Maps/LocalizedStrings/uk.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/uk.lproj/Localizable.strings index cd2b8d929..43e503cfa 100644 --- a/iphone/Maps/LocalizedStrings/uk.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/uk.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Так"; /* E.g. "WiFi:No" */ "no_available" = "Ні"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Місткість: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Мережа: %@"; "trip_finished" = "Ви прибули!"; diff --git a/iphone/Maps/LocalizedStrings/uk.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/uk.lproj/LocalizableTypes.strings index f0c9e933b..a6936c9b6 100644 --- a/iphone/Maps/LocalizedStrings/uk.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/uk.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "Тунель"; "type.highway.bus_stop" = "Зупинка"; "type.highway.construction" = "Дорога, що будується"; +"type.highway.construction.motorway" = "Дорога, що будується"; +"type.highway.construction.motorway_link" = "Дорога, що будується"; +"type.highway.construction.trunk" = "Дорога, що будується"; +"type.highway.construction.trunk_link" = "Дорога, що будується"; +"type.highway.construction.primary" = "Дорога, що будується"; +"type.highway.construction.primary_link" = "Дорога, що будується"; +"type.highway.construction.secondary" = "Дорога, що будується"; +"type.highway.construction.secondary_link" = "Дорога, що будується"; +"type.highway.construction.tertiary" = "Дорога, що будується"; +"type.highway.construction.tertiary_link" = "Дорога, що будується"; +"type.highway.construction.residential" = "Дорога, що будується"; +"type.highway.construction.unclassified" = "Дорога, що будується"; +"type.highway.construction.service" = "Дорога, що будується"; +"type.highway.construction.living_street" = "Дорога, що будується"; +"type.highway.construction.road" = "Дорога, що будується"; +"type.highway.construction.track" = "Дорога, що будується"; "type.highway.cycleway" = "Велодоріжка"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Міст"; diff --git a/iphone/Maps/LocalizedStrings/vi.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/vi.lproj/Localizable.strings index 1d11765c5..1308a8daf 100644 --- a/iphone/Maps/LocalizedStrings/vi.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/vi.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "Có"; /* E.g. "WiFi:No" */ "no_available" = "Không"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "Công suất: %@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "Mạng: %@"; "trip_finished" = "Bạn đã tới nơi!"; diff --git a/iphone/Maps/LocalizedStrings/vi.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/vi.lproj/LocalizableTypes.strings index 43dd71efb..bf5d4818f 100644 --- a/iphone/Maps/LocalizedStrings/vi.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/vi.lproj/LocalizableTypes.strings @@ -453,6 +453,22 @@ "type.highway.bus_stop" = "Bến xe buýt"; "type.highway.construction" = "Đường đang thi công"; "type.highway.cycleway" = "Đường dành cho xe đạp"; +"type.highway.construction.motorway" = "Đường đang thi công"; +"type.highway.construction.motorway_link" = "Đường đang thi công"; +"type.highway.construction.trunk" = "Đường đang thi công"; +"type.highway.construction.trunk_link" = "Đường đang thi công"; +"type.highway.construction.primary" = "Đường đang thi công"; +"type.highway.construction.primary_link" = "Đường đang thi công"; +"type.highway.construction.secondary" = "Đường đang thi công"; +"type.highway.construction.secondary_link" = "Đường đang thi công"; +"type.highway.construction.tertiary" = "Đường đang thi công"; +"type.highway.construction.tertiary_link" = "Đường đang thi công"; +"type.highway.construction.residential" = "Đường đang thi công"; +"type.highway.construction.unclassified" = "Đường đang thi công"; +"type.highway.construction.service" = "Đường đang thi công"; +"type.highway.construction.living_street" = "Đường đang thi công"; +"type.highway.construction.road" = "Đường đang thi công"; +"type.highway.construction.track" = "Đường đang thi công"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "Cầu"; "type.highway.cycleway.permissive" = "Đường dành cho xe đạp"; diff --git a/iphone/Maps/LocalizedStrings/zh-Hans.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/zh-Hans.lproj/Localizable.strings index 2fa86c27e..783b7addb 100644 --- a/iphone/Maps/LocalizedStrings/zh-Hans.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/zh-Hans.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "是"; /* E.g. "WiFi:No" */ "no_available" = "否"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "容量:%@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "网络:%@"; "trip_finished" = "您已到达目的地!"; diff --git a/iphone/Maps/LocalizedStrings/zh-Hans.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/zh-Hans.lproj/LocalizableTypes.strings index 28f2ea8fc..41dd629ba 100644 --- a/iphone/Maps/LocalizedStrings/zh-Hans.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/zh-Hans.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "隧道"; "type.highway.bus_stop" = "公交站"; "type.highway.construction" = "在建道路"; +"type.highway.construction.motorway" = "在建道路"; +"type.highway.construction.motorway_link" = "在建道路"; +"type.highway.construction.trunk" = "在建道路"; +"type.highway.construction.trunk_link" = "在建道路"; +"type.highway.construction.primary" = "在建道路"; +"type.highway.construction.primary_link" = "在建道路"; +"type.highway.construction.secondary" = "在建道路"; +"type.highway.construction.secondary_link" = "在建道路"; +"type.highway.construction.tertiary" = "在建道路"; +"type.highway.construction.tertiary_link" = "在建道路"; +"type.highway.construction.residential" = "在建道路"; +"type.highway.construction.unclassified" = "在建道路"; +"type.highway.construction.service" = "在建道路"; +"type.highway.construction.living_street" = "在建道路"; +"type.highway.construction.road" = "在建道路"; +"type.highway.construction.track" = "在建道路"; "type.highway.cycleway" = "自行车道"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "桥"; diff --git a/iphone/Maps/LocalizedStrings/zh-Hant.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/zh-Hant.lproj/Localizable.strings index 73d301e84..4234ba114 100644 --- a/iphone/Maps/LocalizedStrings/zh-Hant.lproj/Localizable.strings +++ b/iphone/Maps/LocalizedStrings/zh-Hant.lproj/Localizable.strings @@ -681,8 +681,6 @@ "yes_available" = "是"; /* E.g. "WiFi:No" */ "no_available" = "否"; -/* To indicate the capacity of car parkings, bicycle parkings, electric vehicle charging stations... */ -"capacity" = "容量:%@"; /* To indicate the network of ATMs, bicycle rentals, electric vehicle charging stations... */ "network" = "網路: %@"; "trip_finished" = "您已到達目的地!"; diff --git a/iphone/Maps/LocalizedStrings/zh-Hant.lproj/LocalizableTypes.strings b/iphone/Maps/LocalizedStrings/zh-Hant.lproj/LocalizableTypes.strings index 498107279..5a8818012 100644 --- a/iphone/Maps/LocalizedStrings/zh-Hant.lproj/LocalizableTypes.strings +++ b/iphone/Maps/LocalizedStrings/zh-Hant.lproj/LocalizableTypes.strings @@ -452,6 +452,22 @@ "type.highway.busway.tunnel" = "隧道"; "type.highway.bus_stop" = "公車站"; "type.highway.construction" = "施工中道路"; +"type.highway.construction.motorway" = "施工中道路"; +"type.highway.construction.motorway_link" = "施工中道路"; +"type.highway.construction.trunk" = "施工中道路"; +"type.highway.construction.trunk_link" = "施工中道路"; +"type.highway.construction.primary" = "施工中道路"; +"type.highway.construction.primary_link" = "施工中道路"; +"type.highway.construction.secondary" = "施工中道路"; +"type.highway.construction.secondary_link" = "施工中道路"; +"type.highway.construction.tertiary" = "施工中道路"; +"type.highway.construction.tertiary_link" = "施工中道路"; +"type.highway.construction.residential" = "施工中道路"; +"type.highway.construction.unclassified" = "施工中道路"; +"type.highway.construction.service" = "施工中道路"; +"type.highway.construction.living_street" = "施工中道路"; +"type.highway.construction.road" = "施工中道路"; +"type.highway.construction.track" = "施工中道路"; "type.highway.cycleway" = "單車道"; /* These translations are used for all type.highway.*.bridge. */ "type.highway.cycleway.bridge" = "橋樑"; diff --git a/iphone/Maps/UI/PlacePage/Components/PlacePageInfoViewController.swift b/iphone/Maps/UI/PlacePage/Components/PlacePageInfoViewController.swift index c747999bc..b9ed476ff 100644 --- a/iphone/Maps/UI/PlacePage/Components/PlacePageInfoViewController.swift +++ b/iphone/Maps/UI/PlacePage/Components/PlacePageInfoViewController.swift @@ -69,6 +69,8 @@ class PlacePageInfoViewController: UIViewController { private var driveThroughView: InfoItemView? private var networkView: InfoItemView? private var populationView: InfoItemView? + private var capacityDisabledView: InfoItemView? + private var capacityChargingView: InfoItemView? weak var placePageInfoData: PlacePageInfoData! weak var delegate: PlacePageInfoViewControllerDelegate? @@ -211,6 +213,14 @@ class PlacePageInfoViewController: UIViewController { if let capacity = placePageInfoData.capacity { capacityView = createInfoItem(capacity, icon: UIImage(systemName: "viewfinder")) } + + if let capacityCharging = placePageInfoData.capacityCharging { + capacityChargingView = createInfoItem(capacityCharging, icon: UIImage(named: "powerplug.portrait.viewfinder")) + } + + if let capacityDisabled = placePageInfoData.capacityDisabled { + capacityDisabledView = createInfoItem(capacityDisabled, icon: UIImage(named: "figure.roll.viewfinder")) + } if let rooms = placePageInfoData.rooms { roomsView = createInfoItem(rooms, icon: UIImage(systemName: "bed.double.fill")) diff --git a/libs/indexer/feature_meta.cpp b/libs/indexer/feature_meta.cpp index 42d307a61..2957c91f4 100644 --- a/libs/indexer/feature_meta.cpp +++ b/libs/indexer/feature_meta.cpp @@ -150,7 +150,7 @@ bool Metadata::TypeFromString(string_view k, Metadata::EType & outType) // Process only _main_ tag here, needed for editor ser/des. Actual postcode parsing happens in GetNameAndType. else if (k == "addr:postcode") outType = Metadata::FMD_POSTCODE; - else if (k == "wikipedia") + else if (k == "wikipedia" || k == "subject:wikipedia") outType = Metadata::FMD_WIKIPEDIA; else if (k == "wikimedia_commons") outType = Metadata::FMD_WIKIMEDIA_COMMONS; @@ -200,6 +200,10 @@ bool Metadata::TypeFromString(string_view k, Metadata::EType & outType) outType = Metadata::FMD_CHARGE; else if (k == "population") outType = Metadata::FMD_POPULATION; + else if (k == "capacity:disabled") + outType = Metadata::FMD_CAPACITY_DISABLED; + else if (k == "capacity:charging") + outType = Metadata::FMD_CAPACITY_CHARGING; else return false; @@ -350,6 +354,8 @@ string ToString(Metadata::EType type) case Metadata::FMD_ROOMS: return "rooms"; case Metadata::FMD_CHARGE: return "charge"; case Metadata::FMD_POPULATION: return "population"; + case Metadata::FMD_CAPACITY_DISABLED: return "capacity:disabled"; + case Metadata::FMD_CAPACITY_CHARGING: return "capacity:charging"; case Metadata::FMD_COUNT: CHECK(false, ("FMD_COUNT can not be used as a type.")); }; diff --git a/libs/indexer/feature_meta.hpp b/libs/indexer/feature_meta.hpp index 79b4dd5c6..ddb533848 100644 --- a/libs/indexer/feature_meta.hpp +++ b/libs/indexer/feature_meta.hpp @@ -131,6 +131,8 @@ class Metadata : public MetadataBase FMD_ROOMS = 57, FMD_CHARGE = 58, FMD_POPULATION = 59, + FMD_CAPACITY_DISABLED = 60, + FMD_CAPACITY_CHARGING = 61, FMD_COUNT }; diff --git a/libs/indexer/imported_source.hpp b/libs/indexer/imported_source.hpp new file mode 100644 index 000000000..1a90dca84 --- /dev/null +++ b/libs/indexer/imported_source.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace indexer +{ + +inline constexpr uint8_t kOpenAddressesEditableKey = 0; + +} // namespace indexer diff --git a/libs/indexer/map_object.cpp b/libs/indexer/map_object.cpp index cba8ac60b..57d6c62e1 100644 --- a/libs/indexer/map_object.cpp +++ b/libs/indexer/map_object.cpp @@ -265,6 +265,15 @@ std::string MapObject::GetRooms() const { return std::string(m_metadata.Get(MetadataID::FMD_ROOMS)); } +std::string MapObject::GetCapacityDisabled() const +{ + return std::string(m_metadata.Get(MetadataID::FMD_CAPACITY_DISABLED)); +} + +std::string MapObject::GetCapacityCharging() const +{ + return std::string(m_metadata.Get(MetadataID::FMD_CAPACITY_CHARGING)); +} std::string MapObject::GetPopulation() const { diff --git a/libs/indexer/map_object.hpp b/libs/indexer/map_object.hpp index 19407f74e..3837f564e 100644 --- a/libs/indexer/map_object.hpp +++ b/libs/indexer/map_object.hpp @@ -93,6 +93,8 @@ class MapObject std::string GetRooms() const; std::string GetPopulation() const; std::string GetOrganic() const; + std::string GetCapacityDisabled() const; + std::string GetCapacityCharging() const; /// @returns true if feature has ATM type. bool HasAtm() const; diff --git a/libs/map/framework.cpp b/libs/map/framework.cpp index a8a62d4e9..8f2521f07 100644 --- a/libs/map/framework.cpp +++ b/libs/map/framework.cpp @@ -43,6 +43,7 @@ #include "indexer/categories_holder.hpp" #include "indexer/classificator.hpp" +#include "indexer/custom_keyvalue.hpp" #include "indexer/data_source.hpp" #include "indexer/edit_journal.hpp" #include "indexer/editable_map_object.hpp" @@ -54,6 +55,7 @@ #include "indexer/feature_utils.hpp" #include "indexer/feature_visibility.hpp" #include "indexer/ftypes_matcher.hpp" +#include "indexer/imported_source.hpp" #include "indexer/map_style_reader.hpp" #include "indexer/scales.hpp" #include "indexer/transliteration_loader.hpp" @@ -2974,9 +2976,28 @@ bool Framework::GetEditableMapObject(FeatureID const & fid, osm::EditableMapObje return false; emo = {}; - emo.SetFromFeatureType(*ft); auto const & editor = osm::Editor::Instance(); - emo.SetEditableProperties(editor.GetEditableProperties(*ft)); + + bool const isImported = indexer::CustomKeyValue(ft->GetMetadata(feature::Metadata::FMD_CUSTOM_IDS)) + .Get(indexer::kOpenAddressesEditableKey).value_or(0) != 0; + if (isImported) + { + // Imported address features have no real OSM IDs. Treat editing as creating a new OSM node + // pre-populated with the imported address data. + auto const addrType = classif().GetTypeByPath({"building", "address"}); + if (!editor.CreatePoint(addrType, feature::GetCenter(*ft), fid.m_mwmId, emo)) + { + LOG(LERROR, ("Imported address: CreatePoint failed for feature:", fid)); + return false; + } + emo.SetHouseNumber(ft->GetHouseNumber()); + emo.SetPostcode(std::string(ft->GetMetadata(feature::Metadata::FMD_POSTCODE))); + } + else + { + emo.SetFromFeatureType(*ft); + emo.SetEditableProperties(editor.GetEditableProperties(*ft)); + } auto const & dataSource = m_featuresFetcher.GetDataSource(); search::ReverseGeocoder const coder(dataSource); diff --git a/libs/map/place_page_info.cpp b/libs/map/place_page_info.cpp index cbe87ff03..74099b2ec 100644 --- a/libs/map/place_page_info.cpp +++ b/libs/map/place_page_info.cpp @@ -4,9 +4,12 @@ #include "map/bookmark_manager.hpp" #include "map/track.hpp" +#include "indexer/classificator.hpp" +#include "indexer/custom_keyvalue.hpp" #include "indexer/feature.hpp" #include "indexer/feature_utils.hpp" #include "indexer/ftypes_matcher.hpp" +#include "indexer/imported_source.hpp" #include "indexer/mwm_set.hpp" #include "indexer/road_shields_parser.hpp" @@ -305,7 +308,19 @@ void Info::SetBookmarkId(kml::MarkId bookmarkId) bool Info::ShouldShowEditPlace() const { // TODO(mgsergio): Does IsFeature() imply !IsMyPosition()? - return !IsMyPosition() && IsFeature(); + if (IsMyPosition() || !IsFeature()) + return false; + + static auto const kAddrType = classif().GetTypeByPath({"building", "address"}); + if (GetTypes().Has(kAddrType)) + { + auto const customIds = GetMetadata(feature::Metadata::FMD_CUSTOM_IDS); + if (!customIds.empty() && + indexer::CustomKeyValue(customIds).Get(indexer::kOpenAddressesEditableKey).value_or(0) == 0) + return false; + } + + return true; } kml::LocalizableString Info::FormatNewBookmarkName() const diff --git a/libs/map/routing_manager.cpp b/libs/map/routing_manager.cpp index 671240c63..8cd11745d 100644 --- a/libs/map/routing_manager.cpp +++ b/libs/map/routing_manager.cpp @@ -519,7 +519,7 @@ void RoutingManager::SetRouterImpl(RouterType type) VehicleType const vehicleType = GetVehicleType(type); - m_loadAltitudes = vehicleType != VehicleType::Car; + m_loadAltitudes = (vehicleType != VehicleType::Car) && (vehicleType != VehicleType::Decoder); auto const countryFileGetter = [this](m2::PointD const & p) -> string { diff --git a/libs/platform/mwm_version.hpp b/libs/platform/mwm_version.hpp index f58944f24..02186b4df 100644 --- a/libs/platform/mwm_version.hpp +++ b/libs/platform/mwm_version.hpp @@ -30,7 +30,8 @@ enum class Format // header, sdx section with header, dat section renamed to features, features section with // header). v11, // September 2020 (compressed string storage for metadata). - lastFormat = v11 + v12, // June 2026 (additional vehicle model DecoderModel, construction types allowed in routing section). + lastFormat = v12 }; std::string DebugPrint(Format f); diff --git a/libs/routing/edge_estimator.cpp b/libs/routing/edge_estimator.cpp index 8db4d1f92..2def821e4 100644 --- a/libs/routing/edge_estimator.cpp +++ b/libs/routing/edge_estimator.cpp @@ -826,6 +826,11 @@ shared_ptr EdgeEstimator::Create(VehicleType vehicleType, double case VehicleType::Bicycle: return make_shared(maxWeighSpeedKMpH, offroadSpeedKMpH); case VehicleType::Car: return make_shared(dataSourcePtr, numMwmIds, trafficStash, maxWeighSpeedKMpH, offroadSpeedKMpH); + /* + * VehicleType::Decoder is for use with the TraFF decoder, which creates its EdgeEstimator by + * explicitly calling the constructor for the appropriate subclass. + */ + case VehicleType::Decoder: CHECK(false, ("Creating EdgeEstimator for Decoder is not supported")); return nullptr; case VehicleType::Count: CHECK(false, ("Can't create EdgeEstimator for", vehicleType)); return nullptr; } UNREACHABLE(); diff --git a/libs/routing/index_graph_loader.cpp b/libs/routing/index_graph_loader.cpp index e2884f9af..f07674ca1 100644 --- a/libs/routing/index_graph_loader.cpp +++ b/libs/routing/index_graph_loader.cpp @@ -237,7 +237,12 @@ bool ReadRoadPenaltyFromMwm(MwmValue const & mwmValue, VehicleType vehicleType, // Read number of vehicle types uint32_t numVehicleTypes = ReadPrimitiveFromSource(src); - CHECK_EQUAL(numVehicleTypes, static_cast(VehicleType::Count), ()); + if (numVehicleTypes <= static_cast(vehicleType) + && vehicleType == VehicleType::Decoder + && numVehicleTypes > static_cast(VehicleType::Car)) + // This is expected for older mwm files (up to v11) - not an error + vehicleType = VehicleType::Car; + CHECK(numVehicleTypes > static_cast(vehicleType), ()); // Skip to the correct vehicle type for (uint32_t i = 0; i < static_cast(vehicleType); ++i) diff --git a/libs/routing/index_router.cpp b/libs/routing/index_router.cpp index f56b756ba..7ed74bcf1 100644 --- a/libs/routing/index_router.cpp +++ b/libs/routing/index_router.cpp @@ -36,6 +36,7 @@ #include "routing_common/bicycle_model.hpp" #include "routing_common/car_model.hpp" #include "routing_common/num_mwm_id.hpp" +#include "routing_common/decoder_model.hpp" #include "routing_common/pedestrian_model.hpp" #include "platform/country_file.hpp" @@ -119,6 +120,7 @@ shared_ptr CreateVehicleModelFactory( case VehicleType::Transit: return make_shared(countryParentNameGetterFn); case VehicleType::Bicycle: return make_shared(countryParentNameGetterFn); case VehicleType::Car: return make_shared(countryParentNameGetterFn); + case VehicleType::Decoder: return make_shared(countryParentNameGetterFn); case VehicleType::Count: CHECK(false, ("Can't create VehicleModelFactoryInterface for", vehicleType)); return nullptr; } UNREACHABLE(); @@ -132,7 +134,14 @@ unique_ptr CreateDirectionsEngine(VehicleType vehicleType, sha case VehicleType::Pedestrian: case VehicleType::Transit: return make_unique(dataSource, numMwmIds); case VehicleType::Bicycle: - case VehicleType::Car: return make_unique(dataSource, numMwmIds); + case VehicleType::Car: + case VehicleType::Decoder: + /* + * For `VehicleType::Decoder` the directions engine serves no useful purpose. + * We could return `nullptr` here, but we would have to go through every usage of + * `m_directionsEngine` and ensure it can handle a null pointer. + */ + return make_unique(dataSource, numMwmIds); case VehicleType::Count: CHECK(false, ("Can't create DirectionsEngine for", vehicleType)); return nullptr; } UNREACHABLE(); @@ -566,7 +575,7 @@ RouterResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoints, FakeEnding startFakeEnding = m_guides.GetFakeEnding(i); FakeEnding finishFakeEnding = m_guides.GetFakeEnding(i + 1); - bool isStartSegmentStrictForward = (m_vehicleType == VehicleType::Car); + bool isStartSegmentStrictForward = ((m_vehicleType == VehicleType::Car) || (m_vehicleType == VehicleType::Decoder)); if (startFakeEnding.m_projections.empty() || finishFakeEnding.m_projections.empty()) { bool const isFirstSubroute = (i == checkpoints.GetPassedIdx()); @@ -1817,6 +1826,7 @@ void IndexRouter::SetupAlgorithmMode(IndexGraphStarter & starter, bool guidesAct case VehicleType::Bicycle: starter.GetGraph().SetMode(WorldGraphMode::Joints); break; case VehicleType::Transit: starter.GetGraph().SetMode(WorldGraphMode::NoLeaps); break; case VehicleType::Car: + case VehicleType::Decoder: starter.GetGraph().SetMode(AreMwmsNear(starter) ? WorldGraphMode::Joints : WorldGraphMode::LeapsOnly); break; case VehicleType::Count: CHECK(false, ("Unknown vehicle type:", m_vehicleType)); break; diff --git a/libs/routing/road_access_serialization.cpp b/libs/routing/road_access_serialization.cpp index 7e7191587..1dde0a865 100644 --- a/libs/routing/road_access_serialization.cpp +++ b/libs/routing/road_access_serialization.cpp @@ -11,6 +11,7 @@ std::string DebugPrint(RoadAccessSerializer::Header const & header) case RoadAccessSerializer::Header::TheFirstVersionRoadAccess: return "TheFirstVersionRoadAccess"; case RoadAccessSerializer::Header::WithoutAccessConditional: return "WithoutAccessConditional"; case RoadAccessSerializer::Header::WithAccessConditional: return "WithAccessConditional"; + case RoadAccessSerializer::Header::DecoderModelAccess: return "DecoderModelAccess"; } UNREACHABLE(); } diff --git a/libs/routing/road_access_serialization.hpp b/libs/routing/road_access_serialization.hpp index d0913f66e..a2b007c9b 100644 --- a/libs/routing/road_access_serialization.hpp +++ b/libs/routing/road_access_serialization.hpp @@ -33,11 +33,24 @@ class RoadAccessSerializer final using PointToAccessConditional = RoadAccess::PointToAccessConditional; using RoadAccessByVehicleType = std::array(VehicleType::Count)>; + /** + * @brief Values for the access version header. + * + * Each version introduced a breaking change to the way road access is stored in the MWM, + * requiring a different approach to deserialization. + * + * For any future format changes, append a new value with a descriptive name to this enum, + * and update `kLatestVersion` as well as `kVehicleTypeCount`. + * + * For any new values added here, the corresponding `DebugPrint()` function in the cpp file also + * needs to be updated. + */ enum class Header : uint32_t { - TheFirstVersionRoadAccess = 0, // Version of section roadaccess in 2017. - WithoutAccessConditional = 1, // Section roadaccess before conditional was implemented. - WithAccessConditional = 2 // Section roadaccess with conditional. + TheFirstVersionRoadAccess = 0, //< Version of section roadaccess in 2017. + WithoutAccessConditional = 1, //< Section roadaccess before conditional was implemented. + WithAccessConditional = 2, //< Section roadaccess with conditional. + DecoderModelAccess = 3 //< New vehicle model `DecoderModel` added. }; RoadAccessSerializer() = delete; @@ -59,16 +72,47 @@ class RoadAccessSerializer final switch (header) { case Header::TheFirstVersionRoadAccess: break; // Version of 2017. Unsupported. - case Header::WithoutAccessConditional: DeserializeAccess(src, vehicleType, roadAccess); break; + case Header::WithoutAccessConditional: DeserializeAccess(src, vehicleType, roadAccess, header); break; case Header::WithAccessConditional: - DeserializeAccess(src, vehicleType, roadAccess); - DeserializeAccessConditional(src, vehicleType, roadAccess); + case Header::DecoderModelAccess: + DeserializeAccess(src, vehicleType, roadAccess, header); + DeserializeAccessConditional(src, vehicleType, roadAccess, header); break; } } private: - inline static Header const kLatestVersion = Header::WithAccessConditional; + /** + * @brief Current version of the road access format. + * + * This should always be equal to the last value of `Header` and must be updated whenever format + * changes are introduced that require different processing. + * + * When changing this value, you must ensure backward compatibility with older versions. + */ + inline static Header const kLatestVersion = Header::DecoderModelAccess; + + /** + * @brief Number of vehicle types by version. + * + * Use `Header` as a numeric index into this array to determine the number of vehicle types for + * which access should be read upon encountering that version. + * + * When adding or removing vehicle types, append a new value to `Header` (see there), set + * `kLatestVersion` to that new value, and append an entry here, indicating the new number of + * vehicle types. You also need to review all functions in which `kVehicleTypeCount` is used and + * adapt them as needed to be compatible with both the old and new format. + */ + inline static std::array const kVehicleTypeCount = { + // TheFirstVersionRoadAccess (version of section roadaccess in 2017, no longer supported) + 0, + // WithoutAccessConditional (section roadaccess before conditional was implemented, 4 vehicle types) + 4, + // WithAccessConditional (section roadaccess with conditional, 4 vehicle types) + 4, + // DecoderModelAccess (new vehicle model `DecoderModel` and vehicle type added) + 5 + }; class AccessPosition { @@ -130,13 +174,18 @@ class RoadAccessSerializer final } template - static void DeserializeAccess(Source & src, VehicleType vehicleType, RoadAccess & roadAccess) + static void DeserializeAccess(Source & src, VehicleType vehicleType, RoadAccess & roadAccess, Header header) { - std::array(VehicleType::Count)> sectionSizes{}; - static_assert(static_cast(VehicleType::Count) == 4, - "It is assumed below that there are only 4 vehicle types and we store 4 numbers " - "of sections size. If you add or remove vehicle type you should up " - "|kLatestVersion| and save back compatibility here."); + std::vector sectionSizes(kVehicleTypeCount[static_cast(header)]); + static_assert(kVehicleTypeCount.size() == (static_cast(kLatestVersion) + 1), + "The number of entries in `kVehicleTypeCount` does not match `kLatestVersion`. " + "Ensure `kVehicleTypeCount` has an entry for each possible value of `Header`, " + "and `kLatestVersion` matches the highest possible value of `Header`."); + static_assert(static_cast(VehicleType::Count) == 5, + "The current version of the access header assumes there are exactly 5 vehicle " + "types. Adding or removing vehicle types is a breaking change and requires " + "increasing `kLatestVersion` and updating `kVehicleTypeCount`. See documentation " + "of `kVehicleTypeCount` for details."); for (auto & sectionSize : sectionSizes) sectionSize = ReadPrimitiveFromSource(src); @@ -186,13 +235,18 @@ class RoadAccessSerializer final } template - static void DeserializeAccessConditional(Source & src, VehicleType vehicleType, RoadAccess & roadAccess) + static void DeserializeAccessConditional(Source & src, VehicleType vehicleType, RoadAccess & roadAccess, Header header) { - std::array(VehicleType::Count)> sectionSizes{}; - static_assert(static_cast(VehicleType::Count) == 4, - "It is assumed below that there are only 4 vehicle types and we store 4 numbers " - "of sections size. If you add or remove vehicle type you should up " - "|kLatestVersion| and save back compatibility here."); + std::vector sectionSizes(kVehicleTypeCount[static_cast(header)]); + static_assert(kVehicleTypeCount.size() == (static_cast(kLatestVersion) + 1), + "The number of entries in `kVehicleTypeCount` does not match `kLatestVersion`. " + "Ensure `kVehicleTypeCount` has an entry for each possible value of `Header`, " + "and `kLatestVersion` matches the highest possible value of `Header`."); + static_assert(static_cast(VehicleType::Count) == 5, + "The current version of the access header assumes there are exactly 5 vehicle " + "types. Adding or removing vehicle types is a breaking change and requires " + "increasing `kLatestVersion` and updating `kVehicleTypeCount`. See documentation " + "of `kVehicleTypeCount` for details."); for (auto & sectionSize : sectionSizes) sectionSize = ReadPrimitiveFromSource(src); @@ -341,6 +395,8 @@ class RoadAccessSerializer final } // todo(@m) This code borrows heavily from traffic/traffic_info.hpp:SerializeTrafficKeys. + // SerializeTrafficKeys is from the defunct MapsWithMe traffic module and will be obsoleted by + // the new traffic feature currently under development. template static void SerializeSegments(Sink & sink, std::vector const & segments) { diff --git a/libs/routing/routes_builder/routes_builder.cpp b/libs/routing/routes_builder/routes_builder.cpp index 5c9a85b0b..78f6d77bc 100644 --- a/libs/routing/routes_builder/routes_builder.cpp +++ b/libs/routing/routes_builder/routes_builder.cpp @@ -281,7 +281,7 @@ void RoutesBuilder::Processor::InitRouter(VehicleType type) return cigSharedPtr->GetLimitRectForLeaf(countryId); }; - bool const loadAltitudes = type != VehicleType::Car; + bool const loadAltitudes = (type != VehicleType::Car) && (type != VehicleType::Decoder); if (!m_dataSource) m_dataSource = m_dataSourceStorage.GetDataSource(); diff --git a/libs/routing/routes_builder/routes_builder_tool/utils.cpp b/libs/routing/routes_builder/routes_builder_tool/utils.cpp index cdb24d5e3..8662f95bc 100644 --- a/libs/routing/routes_builder/routes_builder_tool/utils.cpp +++ b/libs/routing/routes_builder/routes_builder_tool/utils.cpp @@ -56,6 +56,8 @@ routing::VehicleType ConvertVehicleTypeFromString(std::string const & str) return routing::VehicleType::Bicycle; if (str == "transit") return routing::VehicleType::Transit; + if (str == "decoder") + return routing::VehicleType::Decoder; CHECK(false, ("Unknown vehicle type:", str)); UNREACHABLE(); diff --git a/libs/routing/routing_settings.cpp b/libs/routing/routing_settings.cpp index f18bbc679..e30b0647b 100644 --- a/libs/routing/routing_settings.cpp +++ b/libs/routing/routing_settings.cpp @@ -75,6 +75,7 @@ RoutingSettings GetRoutingSettings(VehicleType vehicleType) 3 /* m_notSoCloseMaxPointsCount */, 25.0 /* m_notSoCloseMaxDistMeters */}; case VehicleType::Car: + case VehicleType::Decoder: return {true /* useDirectionForRouteBuilding */, true /* m_matchRoute */, true /* m_soundDirection */, diff --git a/libs/routing/vehicle_mask.cpp b/libs/routing/vehicle_mask.cpp index 11c4395ec..22528d4ec 100644 --- a/libs/routing/vehicle_mask.cpp +++ b/libs/routing/vehicle_mask.cpp @@ -15,6 +15,7 @@ std::string DebugPrint(VehicleType vehicleType) case VehicleType::Bicycle: return "Bicycle"; case VehicleType::Car: return "Car"; case VehicleType::Transit: return "Transit"; + case VehicleType::Decoder: return "Decoder"; case VehicleType::Count: return "Count"; } UNREACHABLE(); @@ -35,6 +36,8 @@ void FromString(std::string_view s, VehicleType & vehicleType) vehicleType = VehicleType::Car; else if (s == "Transit") vehicleType = VehicleType::Transit; + else if (s == "Decoder") + vehicleType = VehicleType::Decoder; else { ASSERT(false, ("Could not read VehicleType from string", s)); diff --git a/libs/routing/vehicle_mask.hpp b/libs/routing/vehicle_mask.hpp index 61b31c3fb..6a7d2d146 100644 --- a/libs/routing/vehicle_mask.hpp +++ b/libs/routing/vehicle_mask.hpp @@ -13,7 +13,8 @@ enum class VehicleType Bicycle = 1, Car = 2, Transit = 3, - Count = 4 + Decoder = 4, + Count = 5 }; using VehicleMask = uint32_t; @@ -30,6 +31,7 @@ VehicleMask constexpr kPedestrianMask = GetVehicleMask(VehicleType::Pedestrian); VehicleMask constexpr kBicycleMask = GetVehicleMask(VehicleType::Bicycle); VehicleMask constexpr kCarMask = GetVehicleMask(VehicleType::Car); VehicleMask constexpr kTransitMask = GetVehicleMask(VehicleType::Transit); +VehicleMask constexpr kDecoderMask = GetVehicleMask(VehicleType::Decoder); std::string DebugPrint(VehicleType vehicleType); std::string ToString(VehicleType vehicleType); diff --git a/libs/routing_common/CMakeLists.txt b/libs/routing_common/CMakeLists.txt index f03636b2d..e031491ec 100644 --- a/libs/routing_common/CMakeLists.txt +++ b/libs/routing_common/CMakeLists.txt @@ -6,6 +6,8 @@ set(SRC car_model.cpp car_model.hpp car_model_coefs.hpp # This file is generated by running ../configure.sh script. + decoder_model.cpp + decoder_model.hpp maxspeed_conversion.cpp maxspeed_conversion.hpp num_mwm_id.hpp diff --git a/libs/routing_common/car_model.cpp b/libs/routing_common/car_model.cpp index 167bc0533..6f63c168e 100644 --- a/libs/routing_common/car_model.cpp +++ b/libs/routing_common/car_model.cpp @@ -23,6 +23,10 @@ using namespace routing; // of the route except for some edge cases. SpeedKMpH constexpr kSpeedOffroadKMpH = {0.01 /* weight */, kNotUsed /* eta */}; +/* + * The number of entries must match `kHighwayBasedFactors` and `kHighwayBasedSpeeds` + * in `car_model_coefs.hpp`. + */ VehicleModel::LimitsInitList const kDefaultOptions = { // {HighwayType, passThroughAllowed} {HighwayType::HighwayMotorway, true}, {HighwayType::HighwayMotorwayLink, true}, @@ -33,6 +37,7 @@ VehicleModel::LimitsInitList const kDefaultOptions = { {HighwayType::HighwayResidential, true}, {HighwayType::HighwayUnclassified, true}, {HighwayType::HighwayService, true}, {HighwayType::HighwayLivingStreet, true}, {HighwayType::HighwayRoad, true}, {HighwayType::HighwayTrack, true}, + // Non-highway types {HighwayType::RouteShuttleTrain, true}, {HighwayType::RouteFerry, true}, {HighwayType::ManMadePier, true}}; diff --git a/libs/routing_common/car_model_coefs.hpp b/libs/routing_common/car_model_coefs.hpp index 6a466d946..447f6bbb5 100644 --- a/libs/routing_common/car_model_coefs.hpp +++ b/libs/routing_common/car_model_coefs.hpp @@ -3,6 +3,7 @@ #include "routing_common/vehicle_model.hpp" // These are default car model coefficients for open source developers. +// Both maps, as well as `car_model::kDefaultOptions` (in `car_model.cpp`), must have the same number of entries. namespace routing { diff --git a/libs/routing_common/decoder_model.cpp b/libs/routing_common/decoder_model.cpp new file mode 100644 index 000000000..b11e92f49 --- /dev/null +++ b/libs/routing_common/decoder_model.cpp @@ -0,0 +1,293 @@ +#include "routing_common/decoder_model.hpp" + +#include "indexer/classificator.hpp" + +namespace decoder_model +{ +using namespace routing; + +// See model specifics in different countries here: +// https://wiki.openstreetmap.org/wiki/OSM_tags_for_routing/Access-Restrictions + +// See road types here: +// https://wiki.openstreetmap.org/wiki/Key:highway + +/* + * One meter per second. The TraffEstimator works on distance in meters, not travel time. For code + * which works with speeds and assumes cost to be time-based, a speed of 1 m/s means such + * calculations will effectively return distances in meters. + */ +auto constexpr kOneMpSInKmpH = 3.6; + +/* + * Penalty factor for using a fake segment to get to a nearby road. + * Offroad penalty applies to direct distance whereas road penalty applies to roads, which can be up + * to around 3 times the direct distance (theoretically unlimited). Therefore, a factor of 3–4 times + * the penalty of a well-matched road may be needed to avoid competing with the correct route. + * On the other hand, a very high offroad penalty would give preference to a poorly matched route + * over a well-matched one if it is closer to the reference points. + * Maximum penalty for roads is currently 64 (4 for ramps * 4 for road type * 4 for ref). + * A well-matched road may still have a penalty of around 4 (twice the reduced attribute penalty, or + * once the full attribute penalty). + * A “wrong” road may also just have a penalty of 4 (e.g. road name mismatch, but road class and + * ramp type match). + * A value of 16 has worked well for the DE-B2R-SendlingSued-Passauerstrasse test case. (The + * DE-A10-Werder-GrossKreutz or DE-A115-PotsdamDrewitz-Nuthetal test cases gave incorrect results + * due to lack of fake segments, which was fixed through truncation and now works correctly even + * with an offroad penalty of 128.) + */ +auto constexpr kOffroadPenalty = 16; + +// |kSpeedOffroadKMpH| is a speed which is used for edges that don't lie on road features. +// For example for pure fake edges. In car routing, off road speed for calculation ETA is not used. +// The weight of such edges is considered as 0 seconds. It's especially actual when an airport is +// a start or finish. On the other hand, while route calculation the fake edges are considered +// as quite heavy. The idea behind that is to use the closest edge for the start and the finish +// of the route except for some edge cases. +SpeedKMpH constexpr kSpeedOffroadKMpH = kOneMpSInKmpH / kOffroadPenalty; + +HighwayBasedFactors const kDefaultFactors = { + // {highway class : InOutCityFactor(in city, out city)} + + {HighwayType::HighwayMotorway, InOutCityFactor(1.0)}, + {HighwayType::HighwayMotorwayLink, InOutCityFactor(1.0)}, + {HighwayType::HighwayTrunk, InOutCityFactor(1.0)}, + {HighwayType::HighwayTrunkLink, InOutCityFactor(1.0)}, + + {HighwayType::HighwayPrimary, InOutCityFactor(1.0)}, + {HighwayType::HighwayPrimaryLink, InOutCityFactor(1.0)}, + {HighwayType::HighwaySecondary, InOutCityFactor(1.0)}, + {HighwayType::HighwaySecondaryLink, InOutCityFactor(1.0)}, + + {HighwayType::HighwayTertiary, InOutCityFactor(1.0)}, + {HighwayType::HighwayTertiaryLink, InOutCityFactor(1.0)}, + {HighwayType::HighwayUnclassified, InOutCityFactor(1.0)}, + + {HighwayType::HighwayResidential, InOutCityFactor(1.0)}, + {HighwayType::HighwayLivingStreet, InOutCityFactor(1.0)}, + + {HighwayType::HighwayService, InOutCityFactor(1.0)}, + {HighwayType::HighwayRoad, InOutCityFactor(1.0)}, + {HighwayType::HighwayTrack, InOutCityFactor(1.0)}, + {HighwayType::ManMadePier, InOutCityFactor(1.0)}, + + {HighwayType::RouteFerry, InOutCityFactor(1.0)}, + {HighwayType::RouteShuttleTrain, InOutCityFactor(1.0)}, + + // Generic construction type + {HighwayType::HighwayConstruction, InOutCityFactor(1.0)}, + + // Construction types for each highway type: + {HighwayType::HighwayConstructionMotorway, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionMotorwayLink, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionTrunk, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionTrunkLink, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionPrimary, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionPrimaryLink, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionSecondary, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionSecondaryLink, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionTertiary, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionTertiaryLink, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionResidential, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionUnclassified, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionService, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionLivingStreet, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionRoad, InOutCityFactor(1.0)}, + {HighwayType::HighwayConstructionTrack, InOutCityFactor(1.0)}, +}; + +HighwayBasedSpeeds const kDefaultSpeeds = { + // {highway class : InOutCitySpeedKMpH(in city(weight, eta), out city(weight eta))} + {HighwayType::HighwayMotorway, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayMotorwayLink, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayTrunk, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayTrunkLink, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayPrimary, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayPrimaryLink, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwaySecondary, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwaySecondaryLink, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayTertiary, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayTertiaryLink, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayResidential, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayUnclassified, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayService, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayLivingStreet, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayRoad, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayTrack, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + // The router truncates types to two levels, so we need this in addition to the long construction types + {HighwayType::HighwayConstruction, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + // Construction conterparts to each of the types above + // (needed for the map generator to include them in the routing section) + {HighwayType::HighwayConstructionMotorway, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionMotorwayLink, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionTrunk, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionTrunkLink, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionPrimary, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionPrimaryLink, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionSecondary, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionSecondaryLink, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionTertiary, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionTertiaryLink, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionResidential, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionUnclassified, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionService, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionLivingStreet, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionRoad, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::HighwayConstructionTrack, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + // Non-highway types + {HighwayType::RouteShuttleTrain, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::RouteFerry, InOutCitySpeedKMpH(kOneMpSInKmpH)}, + {HighwayType::ManMadePier, InOutCitySpeedKMpH(kOneMpSInKmpH)}}; + +/* + * The number of entries must match `kHighwayBasedFactors` and `kHighwayBasedSpeeds` + * in `decoder_model_coefs.hpp`. + */ +VehicleModel::LimitsInitList const kDefaultOptions = { + // {HighwayType, passThroughAllowed} + {HighwayType::HighwayMotorway, true}, {HighwayType::HighwayMotorwayLink, true}, + {HighwayType::HighwayTrunk, true}, {HighwayType::HighwayTrunkLink, true}, + {HighwayType::HighwayPrimary, true}, {HighwayType::HighwayPrimaryLink, true}, + {HighwayType::HighwaySecondary, true}, {HighwayType::HighwaySecondaryLink, true}, + {HighwayType::HighwayTertiary, true}, {HighwayType::HighwayTertiaryLink, true}, + {HighwayType::HighwayResidential, true}, {HighwayType::HighwayUnclassified, true}, + {HighwayType::HighwayService, true}, {HighwayType::HighwayLivingStreet, true}, + {HighwayType::HighwayRoad, true}, {HighwayType::HighwayTrack, true}, + // The router truncates types to two levels, so we need this in addition to the long construction types + {HighwayType::HighwayConstruction, true}, + // Construction conterparts to each of the types above + // (needed for the map generator to include them in the routing section) + {HighwayType::HighwayConstructionMotorway, true}, {HighwayType::HighwayConstructionMotorwayLink, true}, + {HighwayType::HighwayConstructionTrunk, true}, {HighwayType::HighwayConstructionTrunkLink, true}, + {HighwayType::HighwayConstructionPrimary, true}, {HighwayType::HighwayConstructionPrimaryLink, true}, + {HighwayType::HighwayConstructionSecondary, true}, {HighwayType::HighwayConstructionSecondaryLink, true}, + {HighwayType::HighwayConstructionTertiary, true}, {HighwayType::HighwayConstructionTertiaryLink, true}, + {HighwayType::HighwayConstructionResidential, true}, {HighwayType::HighwayConstructionUnclassified, true}, + {HighwayType::HighwayConstructionService, true}, {HighwayType::HighwayConstructionLivingStreet, true}, + {HighwayType::HighwayConstructionRoad, true}, {HighwayType::HighwayConstructionTrack, true}, + // Non-highway types + {HighwayType::RouteShuttleTrain, true}, {HighwayType::RouteFerry, true}, + {HighwayType::ManMadePier, true}}; + +VehicleModel::LimitsInitList NoPassThroughLivingStreet() +{ + auto res = kDefaultOptions; + for (auto & e : res) + if (e.m_type == HighwayType::HighwayLivingStreet) + e.m_isPassThroughAllowed = false; + return res; +} + +VehicleModel::LimitsInitList NoPassThroughService(VehicleModel::LimitsInitList res = kDefaultOptions) +{ + for (auto & e : res) + if (e.m_type == HighwayType::HighwayService) + e.m_isPassThroughAllowed = false; + return res; +} + +VehicleModel::LimitsInitList NoTrack() +{ + VehicleModel::LimitsInitList res; + res.reserve(kDefaultOptions.size() - 1); + for (auto const & e : kDefaultOptions) + if (e.m_type != HighwayType::HighwayTrack) + res.push_back(e); + return res; +} + +VehicleModel::LimitsInitList NoPassThroughTrack() +{ + auto res = kDefaultOptions; + for (auto & e : res) + if (e.m_type == HighwayType::HighwayTrack) + e.m_isPassThroughAllowed = false; + return res; +} + +/// @todo Should make some compare constrains (like in CarModel_TrackVsGravelTertiary test) +/// to better fit these factors with reality. I have no idea, how they were set. +VehicleModel::SurfaceInitList const kDecoderSurface = { + // {{surfaceType, surfaceType}, {weightFactor, etaFactor}} + {{"psurface", "paved_good"}, {1.0, 1.0}}, + {{"psurface", "paved_bad"}, {0.6, 0.7}}, + {{"psurface", "unpaved_good"}, {0.4, 0.7}}, + {{"psurface", "unpaved_bad"}, {0.2, 0.3}}}; +} // namespace decoder_model + +namespace routing +{ +DecoderModel::DecoderModel() : DecoderModel(decoder_model::kDefaultOptions) {} + +DecoderModel::DecoderModel(VehicleModel::LimitsInitList const & roadLimits) + : VehicleModel(classif(), roadLimits, decoder_model::kDecoderSurface, + {decoder_model::kDefaultSpeeds, decoder_model::kDefaultFactors}) +{ + ASSERT_EQUAL(decoder_model::kDefaultFactors.size(), decoder_model::kDefaultSpeeds.size(), ()); + ASSERT_EQUAL(decoder_model::kDefaultOptions.size(), decoder_model::kDefaultSpeeds.size(), ()); + + std::vector hwtagYesCar = {"hwtag", "yescar"}; + auto const & cl = classif(); + + m_noType = cl.GetTypeByPath({"hwtag", "nocar"}); + m_yesType = cl.GetTypeByPath(hwtagYesCar); + + // Set small track speed if highway is not in kDefaultSpeeds (path, pedestrian), but marked as yescar. + AddAdditionalRoadTypes(cl, {{std::move(hwtagYesCar), decoder_model::kDefaultSpeeds.at(HighwayType::HighwayTrack)}}); + + // Set max possible (reasonable) car speed. See EdgeEstimator::CalcHeuristic. + SpeedKMpH constexpr kMaxCarSpeedKMpH(200.0); + CHECK_LESS(m_maxModelSpeed, kMaxCarSpeedKMpH, ()); + m_maxModelSpeed = kMaxCarSpeedKMpH; +} + +SpeedKMpH DecoderModel::GetSpeed(FeatureTypes const & types, SpeedParams const & speedParams) const +{ + return GetTypeSpeedImpl(types, speedParams, true /* isCar */); +} + +SpeedKMpH const & DecoderModel::GetOffroadSpeed() const +{ + return decoder_model::kSpeedOffroadKMpH; +} + +// static +DecoderModel const & DecoderModel::AllLimitsInstance() +{ + static DecoderModel const instance; + return instance; +} + +// static +VehicleModel::LimitsInitList const & DecoderModel::GetOptions() +{ + return decoder_model::kDefaultOptions; +} + +DecoderModelFactory::DecoderModelFactory(CountryParentNameGetterFn const & countryParentNameGetterFn) + : VehicleModelFactory(countryParentNameGetterFn) +{ + using namespace decoder_model; + using std::make_shared; + + // Names must be the same with country names from countries.txt + m_models[""] = make_shared(); + + /* + * This section should mirror the definitions in `CarModel`. Any deviations should be considered + * a bug, unless there is a comment stating that this is intentional (and ideally also the reason + * it is needed). + */ + m_models["Austria"] = make_shared(NoPassThroughLivingStreet()); + m_models["Belarus"] = make_shared(NoPassThroughLivingStreet()); + m_models["Brazil"] = make_shared(NoPassThroughService(NoPassThroughTrack())); + m_models["Denmark"] = make_shared(NoTrack()); + m_models["Germany"] = make_shared(NoPassThroughTrack()); + m_models["Hungary"] = make_shared(NoPassThroughLivingStreet()); + m_models["Poland"] = make_shared(NoPassThroughService()); + m_models["Romania"] = make_shared(NoPassThroughLivingStreet()); + m_models["Russian Federation"] = make_shared(NoPassThroughService(NoPassThroughLivingStreet())); + m_models["Slovakia"] = make_shared(NoPassThroughLivingStreet()); + m_models["Ukraine"] = make_shared(NoPassThroughService(NoPassThroughLivingStreet())); +} +} // namespace routing diff --git a/libs/routing_common/decoder_model.hpp b/libs/routing_common/decoder_model.hpp new file mode 100644 index 000000000..005756c26 --- /dev/null +++ b/libs/routing_common/decoder_model.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "routing_common/vehicle_model.hpp" + +namespace routing +{ + +/** + * @brief A `VehicleModel` suitable for TraFF location decoding. + * + * Each instance can have its own set of feature type-specific access limitations. These specify + * which roads can be used by this vehicle, and which roads can only be used for destination + * traffic. + * + * `DecoderModel` is similar to `CarModel`, with the following differences: + * + * Construction types are routable and treated like regular roads (the decoder may still + * exclude them on a case-by-case basis). + * + * Speed is assumed to be 1 m/s for any routable road, and 1 m/s divided by offline penalty for + * offroad. + * + * Instances are typically retrieved from `DecoderModelFactory` or the `AllLimitsInstance()` method. + */ +class DecoderModel : public VehicleModel +{ +public: + DecoderModel(); + explicit DecoderModel(LimitsInitList const & roadLimits); + + // VehicleModelInterface overrides: + SpeedKMpH GetSpeed(FeatureTypes const & types, SpeedParams const & speedParams) const override; + SpeedKMpH const & GetOffroadSpeed() const override; + + /** + * @brief Returns an instance with the default access limitations. + */ + static DecoderModel const & AllLimitsInstance(); + + /** + * @brief Returns the default access limitations. + */ + static LimitsInitList const & GetOptions(); +}; + +class DecoderModelFactory : public VehicleModelFactory +{ +public: + DecoderModelFactory(CountryParentNameGetterFn const & countryParentNameGetterF); +}; +} // namespace routing diff --git a/libs/routing_common/vehicle_model.cpp b/libs/routing_common/vehicle_model.cpp index 4b4566271..2d56efee6 100644 --- a/libs/routing_common/vehicle_model.cpp +++ b/libs/routing_common/vehicle_model.cpp @@ -360,6 +360,23 @@ string DebugPrint(HighwayType type) case HighwayType::HighwayPedestrian: return "highway-pedestrian"; case HighwayType::HighwayTrunkLink: return "highway-trunk_link"; case HighwayType::HighwayPrimaryLink: return "highway-primary_link"; + case HighwayType::HighwayConstruction: return "highway-construction"; + case HighwayType::HighwayConstructionMotorway: return "highway-construction-motorway"; + case HighwayType::HighwayConstructionMotorwayLink: return "highway-construction-motorway_link"; + case HighwayType::HighwayConstructionTrunk: return "highway-construction-trunk"; + case HighwayType::HighwayConstructionTrunkLink: return "highway-construction-trunk-link"; + case HighwayType::HighwayConstructionPrimary: return "highway-construction-primary"; + case HighwayType::HighwayConstructionPrimaryLink: return "highway-construction-primary_link"; + case HighwayType::HighwayConstructionSecondary: return "highway-construction-secondary"; + case HighwayType::HighwayConstructionSecondaryLink: return "highway-construction-secondary_link"; + case HighwayType::HighwayConstructionTertiary: return "highway-construction-tertiary"; + case HighwayType::HighwayConstructionTertiaryLink: return "highway-construction-tertiary_link"; + case HighwayType::HighwayConstructionResidential: return "highway-construction-residential"; + case HighwayType::HighwayConstructionUnclassified: return "highway-construction-unclassified"; + case HighwayType::HighwayConstructionService: return "highway-construction-service"; + case HighwayType::HighwayConstructionLivingStreet: return "highway-construction-living_street"; + case HighwayType::HighwayConstructionRoad: return "highway-construction-road"; + case HighwayType::HighwayConstructionTrack: return "highway-construction-track"; case HighwayType::ManMadePier: return "man_made-pier"; case HighwayType::HighwayBridleway: return "highway-bridleway"; case HighwayType::HighwaySecondaryLink: return "highway-secondary_link"; @@ -389,7 +406,16 @@ void FromString(std::string_view s, HighwayType & highwayType) HighwayType::HighwayTrunk, HighwayType::HighwayPedestrian, HighwayType::HighwayTrunkLink, HighwayType::HighwayPrimaryLink, HighwayType::ManMadePier, HighwayType::HighwayBridleway, HighwayType::HighwaySecondaryLink, HighwayType::RouteFerry, HighwayType::HighwayTertiaryLink, - HighwayType::HighwayBusway, HighwayType::RouteShuttleTrain}; + HighwayType::HighwayBusway, HighwayType::RouteShuttleTrain, HighwayType::HighwayConstruction, + HighwayType::HighwayConstructionMotorway, HighwayType::HighwayConstructionMotorwayLink, + HighwayType::HighwayConstructionTrunk, HighwayType::HighwayConstructionTrunkLink, + HighwayType::HighwayConstructionPrimary, HighwayType::HighwayConstructionPrimaryLink, + HighwayType::HighwayConstructionSecondary, HighwayType::HighwayConstructionSecondaryLink, + HighwayType::HighwayConstructionTertiary, HighwayType::HighwayConstructionTertiaryLink, + HighwayType::HighwayConstructionResidential, HighwayType::HighwayConstructionUnclassified, + HighwayType::HighwayConstructionService, HighwayType::HighwayConstructionLivingStreet, + HighwayType::HighwayConstructionRoad, HighwayType::HighwayConstructionTrack, + }; for (auto type : allTypes) map[DebugPrint(type)] = type; diff --git a/libs/routing_common/vehicle_model.hpp b/libs/routing_common/vehicle_model.hpp index 9251b5c8a..ee68f41ab 100644 --- a/libs/routing_common/vehicle_model.hpp +++ b/libs/routing_common/vehicle_model.hpp @@ -54,6 +54,24 @@ enum class HighwayType : uint16_t HighwayTrunkLink = 90, HighwayPrimaryLink = 95, ManMadePier = 119, + // HighwayConstruction and its subtypes are needed for traffic message decoding + HighwayConstruction = 162, + HighwayConstructionMotorway = 789, + HighwayConstructionMotorwayLink = 790, + HighwayConstructionTrunk = 791, + HighwayConstructionTrunkLink = 792, + HighwayConstructionPrimary = 793, + HighwayConstructionPrimaryLink = 794, + HighwayConstructionSecondary = 795, + HighwayConstructionSecondaryLink = 796, + HighwayConstructionTertiary = 797, + HighwayConstructionTertiaryLink = 798, + HighwayConstructionResidential = 799, + HighwayConstructionUnclassified = 800, + HighwayConstructionService = 801, + HighwayConstructionLivingStreet = 802, + HighwayConstructionRoad = 803, + HighwayConstructionTrack = 804, HighwayBridleway = 167, HighwaySecondaryLink = 176, RouteFerry = 259, diff --git a/tools/python/maps_generator/generator/openaddresses_preprocessor.py b/tools/python/maps_generator/generator/openaddresses_preprocessor.py new file mode 100644 index 000000000..534ad18c5 --- /dev/null +++ b/tools/python/maps_generator/generator/openaddresses_preprocessor.py @@ -0,0 +1,477 @@ +#!/usr/bin/env python3 +"""Converts an OpenAddresses ZIP to CoMaps .tempaddr address files. + +Each address is assigned to a MWM region by point-in-polygon lookup against +the .poly border files in the CoMaps borders directory. This correctly handles +countries where provinces/states are split into multiple MWM regions (e.g. +Canada_British_Columbia_Vancouver vs Canada_British_Columbia_Northeast). + +Usage: + python3 openaddresses_preprocessor.py --borders-dir + +The borders directory should contain the .poly files from the CoMaps repository +(data/borders/). Shapely is required for spatial operations. +""" + +import argparse +import io +import json +import logging +import math +import os +import re +import urllib.error +import urllib.request +import zipfile + +from shapely.geometry import Point, Polygon +from shapely.strtree import STRtree + +logger = logging.getLogger("maps_generator") + +_COORD_BITS: int = 30 +_COORD_SIZE: float = (1 << _COORD_BITS) - 1 + +_MIN_X: float = -180.0 +_MAX_X: float = 180.0 +_MIN_Y: float = -180.0 +_MAX_Y: float = 180.0 + +_INTERPOL_NONE: int = 0 + +_ADDR_EXT: str = ".tempaddr" + + +def _write_varuint(f: io.RawIOBase, value: int) -> None: + value = int(value) & 0xFFFFFFFFFFFFFFFF + while value > 127: + f.write(bytes([(value & 127) | 128])) + value >>= 7 + f.write(bytes([value])) + + +def _zigzag_encode(v: int) -> int: + v = int(v) + return ((v << 1) ^ (v >> 63)) & 0xFFFFFFFFFFFFFFFF + + +def _write_varint(f: io.RawIOBase, value: int) -> None: + _write_varuint(f, _zigzag_encode(value)) + + +def _write_string(f: io.RawIOBase, s: str) -> None: + encoded = s.encode("utf-8") + _write_varuint(f, len(encoded)) + if encoded: + f.write(encoded) + + +def _lat_to_y(lat: float) -> float: + lat = max(-86.0, min(86.0, lat)) + sinx = math.sin(math.radians(lat)) + res = math.degrees(0.5 * math.log((1.0 + sinx) / (1.0 - sinx))) + return max(_MIN_Y, min(_MAX_Y, res)) + + +def _double_to_uint32(x: float, min_v: float, max_v: float) -> int: + if x <= min_v: + d = 0.0 + elif x >= max_v: + d = _COORD_SIZE + else: + d = (x - min_v) / (max_v - min_v) * _COORD_SIZE + return int(0.5 + d) + + +def _perfect_shuffle(x: int) -> int: + x &= 0xFFFFFFFFFFFFFFFF + x = ((x & 0x00000000FFFF0000) << 16) | ((x >> 16) & 0x00000000FFFF0000) | (x & 0xFFFF00000000FFFF) + x = ((x & 0x0000FF000000FF00) << 8) | ((x >> 8) & 0x0000FF000000FF00) | (x & 0xFF0000FFFF0000FF) + x = ((x & 0x00F000F000F000F0) << 4) | ((x >> 4) & 0x00F000F000F000F0) | (x & 0xF00FF00FF00FF00F) + x = ((x & 0x0C0C0C0C0C0C0C0C) << 2) | ((x >> 2) & 0x0C0C0C0C0C0C0C0C) | (x & 0xC3C3C3C3C3C3C3C3) + x = ((x & 0x2222222222222222) << 1) | ((x >> 1) & 0x2222222222222222) | (x & 0x9999999999999999) + return x & 0xFFFFFFFFFFFFFFFF + + +def _point_to_int64(lon: float, lat: float) -> int: + ux = _double_to_uint32(lon, _MIN_X, _MAX_X) + uy = _double_to_uint32(_lat_to_y(lat), _MIN_Y, _MAX_Y) + return int(_perfect_shuffle((uy << 32) | ux)) + + +def _parse_poly(path: str) -> list[list[tuple[float, float]]]: + """Parse an OSM .poly file into a list of rings. + + Each ring is a list of (lon, lat) tuples. Rings whose index line starts + with '!' are holes and are returned as-is (callers decide how to handle + them; for point-in-polygon purposes holes are ignored — a point inside a + hole is still inside the outer polygon for MWM assignment). + """ + rings: list[list[tuple[float, float]]] = [] + current: list[tuple[float, float]] | None = None + with open(path, encoding="utf-8") as fh: + for i, line in enumerate(fh): + stripped = line.strip() + if i == 0: + continue + if stripped == "END": + if current is not None: + rings.append(current) + current = None + continue + if stripped.lstrip("!").isdigit(): # "!N" = hole ring + current = [] + continue + if current is not None and stripped: + parts = stripped.split() + if len(parts) >= 2: + try: + lon = float(parts[0]) + lat = float(parts[1]) + current.append((lon, lat)) + except ValueError: + pass + return rings + + +class _BorderIndex: + """Spatial index over .poly border files for point-in-polygon lookup.""" + + def __init__(self, borders_dir: str) -> None: + poly_files = [ + f for f in os.listdir(borders_dir) if f.endswith(".poly") + ] + if not poly_files: + raise ValueError(f"No .poly files found in {borders_dir}") + + self._names: list[str] = [] + self._polys: list[Polygon] = [] + + logger.info(f"Loading {len(poly_files)} border polygons...") + for fn in poly_files: + rings = _parse_poly(os.path.join(borders_dir, fn)) + if not rings: + continue + outer = rings[0] + holes = rings[1:] if len(rings) > 1 else [] + self._names.append(fn[:-5]) + self._polys.append(Polygon(outer, holes)) + + self._strtree = STRtree(self._polys) + + def find(self, lon: float, lat: float) -> str | None: + """Return the MWM name for the region containing (lon, lat), or None.""" + pt = Point(lon, lat) + for idx in self._strtree.query(pt): + if self._polys[idx].contains(pt): + return self._names[idx] + return None + + +def _find_address_geojsons(zf: zipfile.ZipFile) -> list[str]: + """Return all address geojson paths found in the ZIP. + + OA batch output names files ``--.geojson``, + so address files always contain "addresses" in the basename. Countrywide + sources without a sub-national directory may also be named + ``countrywide.geojson`` (no "addresses" component), so we accept either. + + Matches any depth — covers both ``/countrywide.geojson`` (Canada-style) + and ``//-addresses-.geojson`` (US-style) as + well as any future layouts. + """ + found = [] + for name in zf.namelist(): + if not name.endswith(".geojson"): + continue + basename = name.split("/")[-1] + if "addresses" in basename or "countrywide" in basename: + found.append(name) + if not found: + raise ValueError( + "No address geojson files found in ZIP. " + "Expected files whose basename contains 'addresses' or 'countrywide'." + ) + return found + + +_LAYER_SUFFIX_RE = re.compile( + r"-(?:addresses|buildings|parcels|centerlines)-[^/]+\.geojson$", + re.IGNORECASE, +) + +_NC_ND_SUBSTRINGS: tuple[str, ...] = ( + "non-commercial", "noncommercial", + "no derivatives", "no-derivatives", "noderivatives", + "-nc-", "-nc/", "-nd-", "-nd/", +) + + +def _source_key_from_geojson_path(geojson_path: str) -> str: + """Derive the OA source key from a GeoJSON path inside a collection ZIP. + + Examples:: + + 'ca/bc/city_of_victoria-addresses-county.geojson' -> 'ca/bc/city_of_victoria' + 'ca/countrywide.geojson' -> 'ca/countrywide' + """ + key = _LAYER_SUFFIX_RE.sub("", geojson_path) + if key == geojson_path: + key = geojson_path.removesuffix(".geojson") + return key + + +def _license_is_odbl_compatible(license_info) -> bool: + """Return True if a single OA license object is compatible with ODbL. + + Blocklist approach: only reject if explicit NC or ND terms are present. + license_info may be a dict or a bare URL string (both occur in OA data). + """ + if isinstance(license_info, str): + url = license_info.lower() + text = "" + else: + url = (license_info.get("url") or "").lower() + text = (license_info.get("text") or "").lower() + + for term in _NC_ND_SUBSTRINGS: + if term in url or term in text: + return False + + return True + + +_OA_GITHUB_RAW = "https://raw.githubusercontent.com/openaddresses/openaddresses/master" + +# Cache: source_key -> bool (editable or not). Populated lazily during a run. +_source_editable_cache: dict[str, bool] = {} + + +def _load_source_json(source_key: str, oa_sources_dir: str | None = None) -> dict | None: + """Load a source JSON from a local OA repo clone or the OpenAddresses GitHub repo.""" + if oa_sources_dir: + local_path = os.path.join(oa_sources_dir, "sources", source_key + ".json") + try: + with open(local_path, "rb") as f: + return json.loads(f.read().decode("utf-8")) + except FileNotFoundError: + logger.warning(f"Source JSON not found locally for {source_key!r} ({local_path})") + return None + except Exception as exc: + logger.warning(f"Cannot read local source JSON for {source_key!r} ({local_path}): {exc}") + return None + + # The batch ZIP sometimes uses hyphens where the source repo uses underscores + # (e.g. "rouyn-noranda" vs "rouyn_noranda"). Try the original key first, then + # the underscore-normalised form as a fallback. + keys_to_try = [source_key] + normalised = source_key.replace("-", "_") + if normalised != source_key: + keys_to_try.append(normalised) + + for key in keys_to_try: + url = f"{_OA_GITHUB_RAW}/sources/{key}.json" + try: + with urllib.request.urlopen(url, timeout=10) as resp: + return json.loads(resp.read().decode("utf-8")) + except urllib.error.HTTPError as exc: + if exc.code == 404: + continue + logger.warning( + f"Cannot fetch source JSON for {source_key!r} ({url}): {exc};" + " defaulting to ODbL-compatible" + ) + return None + except Exception as exc: + logger.warning( + f"Cannot fetch source JSON for {source_key!r} ({url}): {exc};" + " defaulting to ODbL-compatible" + ) + return None + + logger.warning( + f"Source JSON not found for {source_key!r} on GitHub (HTTP 404);" + " defaulting to ODbL-compatible" + ) + return None + + +def _is_odbl_compatible_source(source_key: str, oa_sources_dir: str | None = None) -> bool: + """Return True if no address layer in the OA source JSON has an explicit + NC or ND license clause. Results are cached for the duration of the run. + + Returns True when the source JSON is missing or has no license field: + absence of an explicit restriction is not a restriction. + """ + if source_key in _source_editable_cache: + return _source_editable_cache[source_key] + + source = _load_source_json(source_key, oa_sources_dir) + if source is None: + _source_editable_cache[source_key] = True + return True + + address_layers = source.get("layers", {}).get("addresses", []) + for layer_entry in address_layers: + license_info = layer_entry.get("license") + if not license_info: + continue + if not _license_is_odbl_compatible(license_info): + logger.info(f"Source {source_key!r} has NC/ND license clause, marking as non-editable.") + _source_editable_cache[source_key] = False + return False + + _source_editable_cache[source_key] = True + return True + + +def process( + zip_path: str, + output_dir: str, + borders_dir: str, + oa_sources_dir: str | None = None, +) -> None: + os.makedirs(output_dir, exist_ok=True) + + index = _BorderIndex(borders_dir) + + writers: dict[str, io.BufferedWriter] = {} + + def get_writer(mwm_name: str) -> io.BufferedWriter: + if mwm_name not in writers: + path = os.path.join(output_dir, mwm_name + _ADDR_EXT) + writers[mwm_name] = open(path, "wb") + writers[mwm_name].write(b"\xff\x01") # tempaddr format header: magic + version + return writers[mwm_name] + + total = 0 + skipped_incomplete = 0 + skipped_region = 0 + skipped_duplicate = 0 + + # Dedup: (mwm_name, number, street, unit). + # ODbL sources are processed first (sorted below), so the first time we + # see an address in a given MWM it wins. Any subsequent record for the + # same (mwm, number, street, unit) is dropped regardless of coordinates. + # This handles both same-region overlap (city + county covering the same + # building) and cross-region name collisions (e.g. a Spokane ODbL address + # and a Yakima county non-ODbL address with the same street name both + # landing in the same MWM polygon). + seen_mwm_addr: set[tuple[str, str, str, str]] = set() + + try: + with zipfile.ZipFile(zip_path, "r") as zf: + geojson_paths = _find_address_geojsons(zf) + # Process ODbL-compatible sources first so they win dedup over NC/ND sources. + # An address present in both ODbL and NC/ND data should remain editable. + geojson_paths = sorted(geojson_paths, + key=lambda p: (0 if _is_odbl_compatible_source(_source_key_from_geojson_path(p), oa_sources_dir) else 1)) + for geojson_path in geojson_paths: + source_key = _source_key_from_geojson_path(geojson_path) + editable = _is_odbl_compatible_source(source_key, oa_sources_dir) + logger.info(f"Processing {geojson_path} (editable={editable})...") + with zf.open(geojson_path) as raw: + for line_bytes in raw: + line_bytes = line_bytes.rstrip(b"\n\r") + if not line_bytes: + continue + total += 1 + + try: + feat = json.loads(line_bytes) + except json.JSONDecodeError: + skipped_incomplete += 1 + continue + + props = feat.get("properties", {}) + number = (props.get("number") or "").strip() + street = (props.get("street") or "").strip() + unit = (props.get("unit") or "").strip() + postcode = (props.get("postcode") or "").strip() + + if not number or not street: + skipped_incomplete += 1 + continue + + geom = feat.get("geometry") or {} + coords = geom.get("coordinates") + if not coords or len(coords) < 2: + skipped_incomplete += 1 + continue + + lon, lat = float(coords[0]), float(coords[1]) + + mwm_name = index.find(lon, lat) + if mwm_name is None: + skipped_region += 1 + continue + + mwm_addr_key = (mwm_name, number, street, unit) + if mwm_addr_key in seen_mwm_addr: + skipped_duplicate += 1 + continue + seen_mwm_addr.add(mwm_addr_key) + + ipoint = _point_to_int64(lon, lat) + + buf = io.BytesIO() + _write_string(buf, number) + _write_string(buf, number) + _write_string(buf, street) + _write_string(buf, postcode) + buf.write(bytes([_INTERPOL_NONE])) + buf.write(bytes([1 if editable else 0])) + _write_varuint(buf, 1) + _write_varint(buf, ipoint) + + get_writer(mwm_name).write(buf.getvalue()) + + finally: + for f in writers.values(): + f.close() + + logger.info( + f"Processed {total} entries: " + f"wrote {total - skipped_incomplete - skipped_region - skipped_duplicate}, " + f"skipped incomplete: {skipped_incomplete}, " + f"skipped no region: {skipped_region}, " + f"skipped duplicate: {skipped_duplicate}" + ) + logger.info(f"Output: {len(writers)} file(s) in {output_dir}") + + +def main() -> None: + parser = argparse.ArgumentParser( + description=( + "Convert an OpenAddresses collection ZIP to CoMaps .tempaddr files. " + "Addresses are assigned to MWM regions via point-in-polygon lookup " + "against the CoMaps .poly border files." + ) + ) + parser.add_argument( + "zip_file", + help="Path to OpenAddresses collection ZIP (e.g. collection-ca.zip)", + ) + parser.add_argument( + "output_dir", + help="Output directory for .tempaddr files (set as ADDRESSES_PATH in the generator)", + ) + parser.add_argument( + "--borders-dir", + required=True, + help="Path to directory containing CoMaps .poly border files (data/borders/)", + ) + parser.add_argument( + "--oa-sources-dir", + default=None, + help=( + "Path to a local clone of github.com/openaddresses/openaddresses. " + "If set, license JSONs are read from disk instead of fetched from GitHub." + ), + ) + args = parser.parse_args() + process(args.zip_file, args.output_dir, args.borders_dir, args.oa_sources_dir) + + +if __name__ == "__main__": + main() diff --git a/tools/python/maps_generator/requirements.txt b/tools/python/maps_generator/requirements.txt index 6618a235f..417198ec4 100644 --- a/tools/python/maps_generator/requirements.txt +++ b/tools/python/maps_generator/requirements.txt @@ -6,3 +6,4 @@ filelock==3.0.10 beautifulsoup4==4.9.1 requests>=2.31.0 requests_file==1.5.1 +shapely>=2.0 diff --git a/tools/python/maps_generator/tests/test_openaddresses_preprocessor.py b/tools/python/maps_generator/tests/test_openaddresses_preprocessor.py new file mode 100644 index 000000000..b7f52f9bd --- /dev/null +++ b/tools/python/maps_generator/tests/test_openaddresses_preprocessor.py @@ -0,0 +1,848 @@ +import importlib.util +import io +import json +import os +import tempfile +import textwrap +import unittest +import zipfile + +_HERE = os.path.dirname(__file__) +_PREPROCESSOR = os.path.normpath( + os.path.join(_HERE, "..", "generator", "openaddresses_preprocessor.py") +) +_spec = importlib.util.spec_from_file_location("openaddresses_preprocessor", _PREPROCESSOR) +_mod = importlib.util.module_from_spec(_spec) +_spec.loader.exec_module(_mod) + +_double_to_uint32 = _mod._double_to_uint32 +_lat_to_y = _mod._lat_to_y +_perfect_shuffle = _mod._perfect_shuffle +_point_to_int64 = _mod._point_to_int64 +_write_string = _mod._write_string +_write_varint = _mod._write_varint +_write_varuint = _mod._write_varuint +_zigzag_encode = _mod._zigzag_encode +_find_address_geojsons = _mod._find_address_geojsons +_parse_poly = _mod._parse_poly +_BorderIndex = _mod._BorderIndex +_COORD_BITS = _mod._COORD_BITS +_COORD_SIZE = _mod._COORD_SIZE +_MIN_X = _mod._MIN_X +_MAX_X = _mod._MAX_X +_MIN_Y = _mod._MIN_Y +_MAX_Y = _mod._MAX_Y + + +class TestWriteVaruint(unittest.TestCase): + def _encode(self, value): + f = io.BytesIO() + _write_varuint(f, value) + return f.getvalue() + + def test_zero(self): + self.assertEqual(self._encode(0), b'\x00') + + def test_one(self): + self.assertEqual(self._encode(1), b'\x01') + + def test_127(self): + self.assertEqual(self._encode(127), b'\x7f') + + def test_128(self): + self.assertEqual(self._encode(128), b'\x80\x01') + + def test_300(self): + self.assertEqual(self._encode(300), b'\xac\x02') + + def test_16383(self): + self.assertEqual(self._encode(16383), b'\xff\x7f') + + def test_16384(self): + self.assertEqual(self._encode(16384), b'\x80\x80\x01') + + + +class TestZigzagEncode(unittest.TestCase): + def test_zero(self): + self.assertEqual(_zigzag_encode(0), 0) + + def test_minus_one(self): + self.assertEqual(_zigzag_encode(-1), 1) + + def test_one(self): + self.assertEqual(_zigzag_encode(1), 2) + + def test_minus_two(self): + self.assertEqual(_zigzag_encode(-2), 3) + + def test_large_positive(self): + self.assertEqual(_zigzag_encode(2147483647), 4294967294) + + def test_large_negative(self): + self.assertEqual(_zigzag_encode(-2147483648), 4294967295) + + + +class TestWriteVarint(unittest.TestCase): + def _encode(self, value): + f = io.BytesIO() + _write_varint(f, value) + return f.getvalue() + + def test_zero(self): + self.assertEqual(self._encode(0), b'\x00') + + def test_minus_one(self): + self.assertEqual(self._encode(-1), b'\x01') + + def test_one(self): + self.assertEqual(self._encode(1), b'\x02') + + def test_minus_64(self): + self.assertEqual(self._encode(-64), b'\x7f') + + def test_64(self): + self.assertEqual(self._encode(64), b'\x80\x01') + + + +class TestWriteString(unittest.TestCase): + def _encode(self, s): + f = io.BytesIO() + _write_string(f, s) + return f.getvalue() + + def test_empty(self): + self.assertEqual(self._encode(""), b'\x00') + + def test_ascii(self): + data = self._encode("42") + self.assertEqual(data, b'\x02' + b'42') + + def test_ascii_street(self): + data = self._encode("Main St") + self.assertEqual(data, b'\x07' + b'Main St') + + def test_utf8(self): + encoded = "café".encode("utf-8") + data = self._encode("café") + self.assertEqual(data, bytes([len(encoded)]) + encoded) + + def test_length_127(self): + s = "x" * 127 + data = self._encode(s) + self.assertEqual(data[0:1], b'\x7f') + self.assertEqual(data[1:], s.encode()) + + def test_length_128(self): + s = "x" * 128 + data = self._encode(s) + self.assertEqual(data[0:2], b'\x80\x01') + self.assertEqual(data[2:], s.encode()) + + + +class TestLatToY(unittest.TestCase): + def test_equator(self): + self.assertAlmostEqual(_lat_to_y(0.0), 0.0, places=10) + + def test_symmetry(self): + for lat in [10.0, 45.0, 60.0, 80.0]: + self.assertAlmostEqual(_lat_to_y(-lat), -_lat_to_y(lat), places=10) + + def test_monotone(self): + lats = [0, 10, 30, 49, 60, 80] + ys = [_lat_to_y(lat_val) for lat_val in lats] + for i in range(len(ys) - 1): + self.assertLess(ys[i], ys[i + 1]) + + def test_clamped_min(self): + self.assertEqual(_lat_to_y(-90.0), _MIN_Y) + + def test_clamped_max(self): + self.assertEqual(_lat_to_y(90.0), _MAX_Y) + + def test_known_value_45(self): + y = _lat_to_y(45.0) + self.assertGreater(y, 49.0) + self.assertLess(y, 52.0) + + def test_vancouver(self): + y = _lat_to_y(49.25) + self.assertGreater(y, 45.0) + self.assertLess(y, 60.0) + + + +class TestDoubleToUint32(unittest.TestCase): + def test_min_boundary(self): + self.assertEqual(_double_to_uint32(_MIN_X, _MIN_X, _MAX_X), 0) + + def test_max_boundary(self): + self.assertEqual(_double_to_uint32(_MAX_X, _MIN_X, _MAX_X), int(_COORD_SIZE)) + + def test_below_min_clamps(self): + self.assertEqual(_double_to_uint32(-200.0, _MIN_X, _MAX_X), 0) + + def test_above_max_clamps(self): + self.assertEqual(_double_to_uint32(200.0, _MIN_X, _MAX_X), int(_COORD_SIZE)) + + def test_center(self): + mid = _double_to_uint32(0.0, _MIN_X, _MAX_X) + expected = round(_COORD_SIZE / 2) + self.assertAlmostEqual(mid, expected, delta=1) + + def test_result_in_range(self): + for lon in [-180, -90, 0, 49.25, 90, 180]: + val = _double_to_uint32(lon, _MIN_X, _MAX_X) + self.assertGreaterEqual(val, 0) + self.assertLessEqual(val, int(_COORD_SIZE)) + + + +class TestPerfectShuffle(unittest.TestCase): + def test_zero(self): + self.assertEqual(_perfect_shuffle(0), 0) + + def test_low_32_bit0(self): + self.assertEqual(_perfect_shuffle(1) & 1, 1) + + def test_high_32_bit0(self): + self.assertEqual((_perfect_shuffle(1 << 32) >> 1) & 1, 1) + + def test_output_fits_64bits(self): + self.assertEqual(_perfect_shuffle(0xFFFFFFFFFFFFFFFF), 0xFFFFFFFFFFFFFFFF) + + + +class TestPointToInt64(unittest.TestCase): + def test_result_is_nonnegative(self): + for lon, lat in [(0, 0), (-123.1, 49.25), (180, 86), (-180, -86)]: + result = _point_to_int64(lon, lat) + self.assertGreaterEqual(result, 0) + + def test_real_coords_nonzero(self): + for lon, lat in [(-123.1, 49.25), (-75.7, 45.4), (-114.1, 51.0)]: + self.assertGreater(_point_to_int64(lon, lat), 0) + + def test_deterministic(self): + p1 = _point_to_int64(-123.1, 49.25) + p2 = _point_to_int64(-123.1, 49.25) + self.assertEqual(p1, p2) + + def test_different_coords_differ(self): + p1 = _point_to_int64(-123.1, 49.25) + p2 = _point_to_int64(-75.7, 45.4) + self.assertNotEqual(p1, p2) + + def test_fits_in_int64(self): + v = _point_to_int64(-123.1, 49.25) + self.assertLessEqual(v, 0x7FFFFFFFFFFFFFFF) + + +class TestRecordRoundTrip(unittest.TestCase): + + def _build_record(self, number, street, postcode, lon, lat, editable=True): + f = io.BytesIO() + _write_string(f, number) + _write_string(f, number) + _write_string(f, street) + _write_string(f, postcode) + f.write(bytes([_mod._INTERPOL_NONE])) + f.write(bytes([1 if editable else 0])) + _write_varuint(f, 1) + _write_varint(f, _point_to_int64(lon, lat)) + return f.getvalue() + + def _parse_record(self, data): + pos = [0] + + def read_varuint(): + result = 0 + shift = 0 + while True: + b = data[pos[0]] + pos[0] += 1 + result |= (b & 0x7F) << shift + if not (b & 0x80): + break + shift += 7 + return result + + def read_varint(): + v = read_varuint() + return (v >> 1) ^ -(v & 1) + + def read_string(): + length = read_varuint() + s = data[pos[0]:pos[0] + length].decode("utf-8") + pos[0] += length + return s + + m_from = read_string() + m_to = read_string() + m_street = read_string() + m_postcode = read_string() + interpol = data[pos[0]] + pos[0] += 1 + editable = data[pos[0]] != 0 + pos[0] += 1 + count = read_varuint() + point = read_varint() + return { + "m_from": m_from, "m_to": m_to, "m_street": m_street, + "m_postcode": m_postcode, "interpol": interpol, + "editable": editable, "count": count, "point": point, + } + + def test_from_equals_to(self): + data = self._build_record("42", "Main St", "V5K 0A1", -123.1, 49.25) + rec = self._parse_record(data) + self.assertEqual(rec["m_from"], "42") + self.assertEqual(rec["m_to"], "42") + self.assertEqual(rec["m_from"], rec["m_to"]) + + def test_street_and_postcode(self): + data = self._build_record("100", "Oak Ave", "V6B 2W2", -123.0, 49.3) + rec = self._parse_record(data) + self.assertEqual(rec["m_street"], "Oak Ave") + self.assertEqual(rec["m_postcode"], "V6B 2W2") + + def test_interpol_none(self): + data = self._build_record("1", "A St", "", -123.0, 49.0) + rec = self._parse_record(data) + self.assertEqual(rec["interpol"], 0) + + def test_point_count_one(self): + data = self._build_record("1", "A St", "", -123.0, 49.0) + rec = self._parse_record(data) + self.assertEqual(rec["count"], 1) + + def test_point_round_trips(self): + lon, lat = -123.1, 49.25 + expected = _point_to_int64(lon, lat) + data = self._build_record("1", "A", "", lon, lat) + rec = self._parse_record(data) + self.assertEqual(rec["point"], expected) + + def test_empty_postcode(self): + data = self._build_record("5", "Elm Rd", "", -75.7, 45.4) + rec = self._parse_record(data) + self.assertEqual(rec["m_postcode"], "") + + def test_record_fully_consumed(self): + data = self._build_record("99", "King St", "K1A 0A6", -75.7, 45.4) + rec = self._parse_record(data) + self.assertEqual(rec["m_from"], "99") + + def test_editable_true(self): + data = self._build_record("1", "A St", "", -123.0, 49.0, editable=True) + rec = self._parse_record(data) + self.assertTrue(rec["editable"]) + + def test_editable_false(self): + data = self._build_record("1", "A St", "", -123.0, 49.0, editable=False) + rec = self._parse_record(data) + self.assertFalse(rec["editable"]) + + +def _write_poly(directory: str, name: str, rings: list) -> str: + """Write a minimal .poly file and return its path. + + rings is a list of lists of (lon, lat) tuples. The first ring is outer; + subsequent rings are holes (prefixed with '!'). + """ + path = os.path.join(directory, name + ".poly") + with open(path, "w") as fh: + fh.write(name + "\n") + for i, ring in enumerate(rings): + prefix = "!" if i > 0 else "" + fh.write(f"{prefix}{i + 1}\n") + for lon, lat in ring: + fh.write(f" {lon:.6E} {lat:.6E}\n") + fh.write("END\n") + fh.write("END\n") + return path + + +_SQUARE = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] + + +class TestFindAddressGeojsons(unittest.TestCase): + def _make_zip(self, names): + buf = io.BytesIO() + with zipfile.ZipFile(buf, "w") as zf: + for name in names: + zf.writestr(name, b"") + buf.seek(0) + return zipfile.ZipFile(buf, "r") + + # --- Canada-style countrywide files --- + + def test_finds_canada_countrywide(self): + zf = self._make_zip(["ca/countrywide-addresses-country.geojson", "ca/other.geojson"]) + result = _find_address_geojsons(zf) + self.assertEqual(result, ["ca/countrywide-addresses-country.geojson"]) + zf.close() + + def test_finds_multiple_countrywide(self): + zf = self._make_zip(["ca/countrywide.geojson", "au/countrywide.geojson", "ca/other.csv"]) + result = _find_address_geojsons(zf) + self.assertIn("ca/countrywide.geojson", result) + self.assertIn("au/countrywide.geojson", result) + self.assertEqual(len(result), 2) + zf.close() + + # --- US-style county/state address files --- + + def test_finds_us_county_addresses(self): + zf = self._make_zip([ + "us/or/marion-addresses-county.geojson", + "us/or/marion-parcels-county.geojson", + "us/or/marion-parcels-county.geojson.meta", + ]) + result = _find_address_geojsons(zf) + self.assertEqual(result, ["us/or/marion-addresses-county.geojson"]) + zf.close() + + def test_finds_us_statewide_addresses(self): + zf = self._make_zip([ + "us/or/statewide-addresses-state.geojson", + "us/or/statewide-buildings-state.geojson", + ]) + result = _find_address_geojsons(zf) + self.assertEqual(result, ["us/or/statewide-addresses-state.geojson"]) + zf.close() + + def test_finds_multiple_us_counties(self): + zf = self._make_zip([ + "us/or/marion-addresses-county.geojson", + "us/or/yamhill-addresses-county.geojson", + "us/wa/king-addresses-county.geojson", + "us/or/marion-parcels-county.geojson", + ]) + result = _find_address_geojsons(zf) + self.assertIn("us/or/marion-addresses-county.geojson", result) + self.assertIn("us/or/yamhill-addresses-county.geojson", result) + self.assertIn("us/wa/king-addresses-county.geojson", result) + self.assertEqual(len(result), 3) + zf.close() + + def test_finds_depth2_addresses_without_countrywide(self): + # e.g. mx/national-addresses-country.geojson — depth 2, no "countrywide" + zf = self._make_zip(["mx/national-addresses-country.geojson", "mx/national-buildings-country.geojson"]) + result = _find_address_geojsons(zf) + self.assertEqual(result, ["mx/national-addresses-country.geojson"]) + zf.close() + + def test_ignores_meta_files(self): + zf = self._make_zip([ + "us/or/marion-addresses-county.geojson", + "us/or/marion-addresses-county.geojson.meta", + ]) + result = _find_address_geojsons(zf) + self.assertEqual(result, ["us/or/marion-addresses-county.geojson"]) + zf.close() + + def test_ignores_non_address_geojsons(self): + zf = self._make_zip([ + "us/or/marion-parcels-county.geojson", + "us/or/statewide-buildings-state.geojson", + ]) + with self.assertRaises(ValueError): + _find_address_geojsons(zf) + zf.close() + + def test_raises_when_empty_zip(self): + zf = self._make_zip(["ca/other.csv", "readme.txt"]) + with self.assertRaises(ValueError): + _find_address_geojsons(zf) + zf.close() + + def test_ignores_non_geojson_extension(self): + zf = self._make_zip(["ca/countrywide.csv", "ca/countrywide.zip"]) + with self.assertRaises(ValueError): + _find_address_geojsons(zf) + zf.close() + + +class TestParsePoly(unittest.TestCase): + def _write(self, content: str) -> str: + fd, path = tempfile.mkstemp(suffix=".poly") + os.write(fd, content.encode()) + os.close(fd) + return path + + def test_single_ring(self): + content = textwrap.dedent("""\ + TestRegion + 1 + 0.0 0.0 + 1.0 0.0 + 1.0 1.0 + 0.0 1.0 + END + END + """) + path = self._write(content) + rings = _parse_poly(path) + os.unlink(path) + self.assertEqual(len(rings), 1) + self.assertEqual(len(rings[0]), 4) + self.assertAlmostEqual(rings[0][0][0], 0.0) + self.assertAlmostEqual(rings[0][0][1], 0.0) + + def test_scientific_notation(self): + content = textwrap.dedent("""\ + TestRegion + 1 + -1.208514E+02 4.900030E+01 + -1.208608E+02 4.900030E+01 + END + END + """) + path = self._write(content) + rings = _parse_poly(path) + os.unlink(path) + self.assertEqual(len(rings), 1) + self.assertAlmostEqual(rings[0][0][0], -120.8514, places=3) + self.assertAlmostEqual(rings[0][0][1], 49.0003, places=3) + + def test_multiple_rings(self): + content = textwrap.dedent("""\ + TestRegion + 1 + 0.0 0.0 + 1.0 0.0 + 1.0 1.0 + END + !2 + 0.2 0.2 + 0.8 0.2 + 0.8 0.8 + END + END + """) + path = self._write(content) + rings = _parse_poly(path) + os.unlink(path) + self.assertEqual(len(rings), 2) + self.assertEqual(len(rings[0]), 3) + self.assertEqual(len(rings[1]), 3) + + def test_empty_file_returns_no_rings(self): + content = "TestRegion\nEND\n" + path = self._write(content) + rings = _parse_poly(path) + os.unlink(path) + self.assertEqual(rings, []) + + +class TestBorderIndex(unittest.TestCase): + def setUp(self): + self.tmpdir = tempfile.mkdtemp() + # Region A: unit square (0,0)-(1,1) + _write_poly(self.tmpdir, "RegionA", [_SQUARE]) + # Region B: unit square (2,0)-(3,1) + _write_poly(self.tmpdir, "RegionB", [[(2.0, 0.0), (3.0, 0.0), (3.0, 1.0), (2.0, 1.0)]]) + + def tearDown(self): + import shutil + shutil.rmtree(self.tmpdir) + + def test_point_in_region_a(self): + idx = _BorderIndex(self.tmpdir) + self.assertEqual(idx.find(0.5, 0.5), "RegionA") + + def test_point_in_region_b(self): + idx = _BorderIndex(self.tmpdir) + self.assertEqual(idx.find(2.5, 0.5), "RegionB") + + def test_point_outside_all(self): + idx = _BorderIndex(self.tmpdir) + self.assertIsNone(idx.find(5.0, 5.0)) + + def test_point_between_regions(self): + idx = _BorderIndex(self.tmpdir) + self.assertIsNone(idx.find(1.5, 0.5)) + + def test_no_poly_files_raises(self): + empty = tempfile.mkdtemp() + try: + with self.assertRaises(ValueError): + _BorderIndex(empty) + finally: + os.rmdir(empty) + + def test_mwm_name_strips_poly_extension(self): + idx = _BorderIndex(self.tmpdir) + result = idx.find(0.5, 0.5) + self.assertFalse(result.endswith(".poly")) + + +class TestProcess(unittest.TestCase): + def setUp(self): + self.tmpdir = tempfile.mkdtemp() + self.borders = tempfile.mkdtemp() + self.output = tempfile.mkdtemp() + _write_poly(self.borders, "TestRegion", [_SQUARE]) + + def tearDown(self): + import shutil + shutil.rmtree(self.tmpdir) + shutil.rmtree(self.borders) + shutil.rmtree(self.output) + + def _make_zip(self, features): + path = os.path.join(self.tmpdir, "test.zip") + lines = "\n".join(json.dumps(f) for f in features) + with zipfile.ZipFile(path, "w") as zf: + zf.writestr("cc/countrywide.geojson", lines) + return path + + def _feat(self, lon, lat, number="42", street="Main St", postcode="V5K 0A1"): + return { + "type": "Feature", + "geometry": {"type": "Point", "coordinates": [lon, lat]}, + "properties": {"number": number, "street": street, "postcode": postcode}, + } + + def _read_records(self, path): + with open(path, "rb") as fh: + data = fh.read() + pos = [0] + records = [] + + def read_varuint(): + result = 0 + shift = 0 + while True: + b = data[pos[0]] + pos[0] += 1 + result |= (b & 0x7F) << shift + if not (b & 0x80): + break + shift += 7 + return result + + def read_varint(): + v = read_varuint() + return (v >> 1) ^ -(v & 1) + + def read_string(): + n = read_varuint() + s = data[pos[0]:pos[0] + n].decode("utf-8") + pos[0] += n + return s + + while pos[0] < len(data): + m_from = read_string() + m_to = read_string() + m_street = read_string() + m_postcode = read_string() + interpol = data[pos[0]] + pos[0] += 1 + editable = data[pos[0]] != 0 + pos[0] += 1 + count = read_varuint() + point = read_varint() + records.append({ + "m_from": m_from, "m_to": m_to, "m_street": m_street, + "m_postcode": m_postcode, "interpol": interpol, + "editable": editable, "count": count, "point": point, + }) + return records + + def test_valid_feature_produces_record(self): + zip_path = self._make_zip([self._feat(0.5, 0.5)]) + _mod.process(zip_path, self.output, self.borders) + out_file = os.path.join(self.output, "TestRegion.tempaddr") + self.assertTrue(os.path.exists(out_file)) + records = self._read_records(out_file) + self.assertEqual(len(records), 1) + r = records[0] + self.assertEqual(r["m_from"], "42") + self.assertEqual(r["m_to"], "42") + self.assertEqual(r["m_street"], "Main St") + self.assertEqual(r["m_postcode"], "V5K 0A1") + self.assertEqual(r["interpol"], 0) + self.assertEqual(r["count"], 1) + self.assertEqual(r["point"], _point_to_int64(0.5, 0.5)) + + def test_feature_outside_region_not_written(self): + zip_path = self._make_zip([self._feat(5.0, 5.0)]) + _mod.process(zip_path, self.output, self.borders) + self.assertEqual(os.listdir(self.output), []) + + def test_incomplete_feature_skipped(self): + zip_path = self._make_zip([ + self._feat(0.5, 0.5, number=""), + self._feat(0.5, 0.5, street=""), + ]) + _mod.process(zip_path, self.output, self.borders) + self.assertEqual(os.listdir(self.output), []) + + def test_multiple_features_same_region(self): + zip_path = self._make_zip([ + self._feat(0.2, 0.2, number="1", street="A St"), + self._feat(0.8, 0.8, number="2", street="B Ave"), + ]) + _mod.process(zip_path, self.output, self.borders) + out_file = os.path.join(self.output, "TestRegion.tempaddr") + records = self._read_records(out_file) + self.assertEqual(len(records), 2) + streets = {r["m_street"] for r in records} + self.assertEqual(streets, {"A St", "B Ave"}) + + def test_mixed_valid_and_invalid(self): + zip_path = self._make_zip([ + self._feat(0.5, 0.5), + self._feat(5.0, 5.0), + self._feat(0.3, 0.3, number=""), + ]) + _mod.process(zip_path, self.output, self.borders) + out_file = os.path.join(self.output, "TestRegion.tempaddr") + records = self._read_records(out_file) + self.assertEqual(len(records), 1) + + +class TestLicenseIsOdblCompatible(unittest.TestCase): + def _check(self, license_info): + return _mod._license_is_odbl_compatible(license_info) + + def test_clean_url_is_compatible(self): + self.assertTrue(self._check({"url": "https://creativecommons.org/licenses/by/4.0/"})) + + def test_nc_url_is_blocked(self): + self.assertFalse(self._check({"url": "https://creativecommons.org/licenses/by-nc/4.0/"})) + + def test_nd_url_is_blocked(self): + self.assertFalse(self._check({"url": "https://creativecommons.org/licenses/by-nd/4.0/"})) + + def test_nc_in_text_is_blocked(self): + self.assertFalse(self._check({"url": "https://example.com/license", "text": "non-commercial use only"})) + + def test_nd_in_text_is_blocked(self): + self.assertFalse(self._check({"url": "", "text": "no derivatives allowed"})) + + def test_bare_string_clean_is_compatible(self): + self.assertTrue(self._check("https://opendatacommons.org/licenses/odbl/")) + + def test_bare_string_nc_is_blocked(self): + self.assertFalse(self._check("https://creativecommons.org/licenses/by-nc-sa/4.0/")) + + def test_odbl_url_is_compatible(self): + self.assertTrue(self._check({"url": "https://opendatacommons.org/licenses/odbl/1.0/"})) + + +class TestSourceKeyFromGeojsonPath(unittest.TestCase): + def _key(self, path): + return _mod._source_key_from_geojson_path(path) + + def test_county_path(self): + self.assertEqual( + self._key("ca/bc/city_of_victoria-addresses-county.geojson"), + "ca/bc/city_of_victoria", + ) + + def test_city_path(self): + self.assertEqual( + self._key("us/wa/city_of_spokane-addresses-city.geojson"), + "us/wa/city_of_spokane", + ) + + def test_countrywide_path(self): + self.assertEqual( + self._key("ca/countrywide.geojson"), + "ca/countrywide", + ) + + def test_no_layer_suffix(self): + self.assertEqual( + self._key("us/or/portland.geojson"), + "us/or/portland", + ) + + +class TestIsOdblCompatibleSource(unittest.TestCase): + def setUp(self): + # Isolate cache between tests. + _mod._source_editable_cache.clear() + + def tearDown(self): + _mod._source_editable_cache.clear() + + def _mock_load(self, source_json): + """Patch _load_source_json to return source_json without HTTP.""" + import unittest.mock + return unittest.mock.patch.object(_mod, "_load_source_json", return_value=source_json) + + def test_odbl_layer_is_compatible(self): + source = { + "layers": { + "addresses": [ + {"license": {"url": "https://opendatacommons.org/licenses/odbl/1.0/"}} + ] + } + } + with self._mock_load(source): + self.assertTrue(_mod._is_odbl_compatible_source("ca/bc/test")) + + def test_nc_layer_is_blocked(self): + source = { + "layers": { + "addresses": [ + {"license": {"url": "https://creativecommons.org/licenses/by-nc/4.0/"}} + ] + } + } + with self._mock_load(source): + self.assertFalse(_mod._is_odbl_compatible_source("ca/bc/nc_source")) + + def test_missing_source_json_defaults_to_true(self): + with self._mock_load(None): + self.assertTrue(_mod._is_odbl_compatible_source("ca/bc/missing")) + + def test_no_license_field_defaults_to_true(self): + source = {"layers": {"addresses": [{"data": "something"}]}} + with self._mock_load(source): + self.assertTrue(_mod._is_odbl_compatible_source("ca/bc/nolicense")) + + def test_result_is_cached(self): + source = { + "layers": { + "addresses": [ + {"license": {"url": "https://creativecommons.org/licenses/by-nc/4.0/"}} + ] + } + } + import unittest.mock + mock_fn = unittest.mock.MagicMock(return_value=source) + with unittest.mock.patch.object(_mod, "_load_source_json", mock_fn): + _mod._is_odbl_compatible_source("ca/bc/cached") + _mod._is_odbl_compatible_source("ca/bc/cached") + self.assertEqual(mock_fn.call_count, 1) + + def test_local_sources_dir_reads_from_disk(self): + source = { + "layers": { + "addresses": [ + {"license": {"url": "https://creativecommons.org/licenses/by-nc/4.0/"}} + ] + } + } + with tempfile.TemporaryDirectory() as d: + source_path = os.path.join(d, "sources", "ca", "bc") + os.makedirs(source_path) + with open(os.path.join(source_path, "test.json"), "w") as f: + json.dump(source, f) + self.assertFalse(_mod._is_odbl_compatible_source("ca/bc/test", d)) + + def test_local_sources_dir_missing_file_defaults_to_true(self): + with tempfile.TemporaryDirectory() as d: + self.assertTrue(_mod._is_odbl_compatible_source("ca/bc/nonexistent", d)) + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/unix/run_oa_preprocessor.sh b/tools/unix/run_oa_preprocessor.sh new file mode 100755 index 000000000..ff802b0e8 --- /dev/null +++ b/tools/unix/run_oa_preprocessor.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# run_oa_preprocessor.sh — Download an OpenAddresses collection and run the CoMaps preprocessor. +# +# Required environment variables: +# OA_API_TOKEN Bearer token for batch.openaddresses.io +# OA_COLLECTION_ID Integer collection ID (e.g. 6 for Canada) +# OA_COLLECTION_NAME Collection name used in filenames/paths (e.g. ca) +# COMAPS_DIR Path to the CoMaps source checkout +# +# Optional environment variables: +# OA_ZIP_PATH Where to save the downloaded ZIP (default: /tmp/collection-oa-${OA_COLLECTION_NAME}.zip) +# OA_OUTPUT_DIR Output dir for .tempaddr files (default: /tmp/oa-out-${OA_COLLECTION_NAME}) +# OA_SOURCES_DIR Local clone of github.com/openaddresses/openaddresses for offline license lookup +# SKIP_DOWNLOAD Set to 1 to skip the download step and use an existing ZIP + +set -euo pipefail + +: "${OA_API_TOKEN:?OA_API_TOKEN is required}" +: "${OA_COLLECTION_ID:?OA_COLLECTION_ID is required}" +: "${OA_COLLECTION_NAME:?OA_COLLECTION_NAME is required}" +: "${COMAPS_DIR:?COMAPS_DIR is required}" + +OA_ZIP_PATH="${OA_ZIP_PATH:-/tmp/collection-oa-${OA_COLLECTION_NAME}.zip}" +OA_OUTPUT_DIR="${OA_OUTPUT_DIR:-/tmp/oa-out-${OA_COLLECTION_NAME}}" +BORDERS_DIR="${COMAPS_DIR}/data/borders" +PREPROCESSOR="${COMAPS_DIR}/tools/python/maps_generator/generator/openaddresses_preprocessor.py" +SKIP_DOWNLOAD="${SKIP_DOWNLOAD:-0}" + +echo "=== OpenAddresses preprocessor for collection ${OA_COLLECTION_NAME} (ID: ${OA_COLLECTION_ID}) ===" + +# --- Download --- +if [ "${SKIP_DOWNLOAD}" != "1" ]; then + echo "Resolving download URL ..." + # Two-step download: the API returns a 302 redirect to the actual file host. + # We resolve the redirect URL first (without -L so %{redirect_url} is populated), + # then download from the resolved URL without the Bearer token. + # Sending the Authorization header directly to the file host may cause errors + # on some S3-compatible hosts that use their own auth in the URL. + DOWNLOAD_URL=$(curl -fsS \ + -H "Authorization: Bearer ${OA_API_TOKEN}" \ + -w "%{redirect_url}" -o /dev/null \ + "https://batch.openaddresses.io/api/collections/${OA_COLLECTION_ID}/data") + + if [ -z "${DOWNLOAD_URL}" ]; then + echo "ERROR: could not resolve download URL for collection ${OA_COLLECTION_ID}" >&2 + exit 1 + fi + + echo "Downloading ${DOWNLOAD_URL} -> ${OA_ZIP_PATH} ..." + [ -f "${OA_ZIP_PATH}" ] && mv -f "${OA_ZIP_PATH}" "${OA_ZIP_PATH}.bak" + curl -fsSL -o "${OA_ZIP_PATH}" "${DOWNLOAD_URL}" + echo "Downloaded $(du -sh "${OA_ZIP_PATH}" | cut -f1)" +else + echo "Skipping download (SKIP_DOWNLOAD=1), using existing: ${OA_ZIP_PATH}" + [ -f "${OA_ZIP_PATH}" ] || { echo "ERROR: ${OA_ZIP_PATH} does not exist" >&2; exit 1; } +fi + +# --- Run preprocessor --- +echo "Preparing output directory: ${OA_OUTPUT_DIR} ..." +rm -rf "${OA_OUTPUT_DIR}.bak" +[ -d "${OA_OUTPUT_DIR}" ] && mv -fT "${OA_OUTPUT_DIR}" "${OA_OUTPUT_DIR}.bak" || true +mkdir -p "${OA_OUTPUT_DIR}" + +PREPROCESSOR_ARGS=( + "${OA_ZIP_PATH}" + "${OA_OUTPUT_DIR}" + --borders-dir "${BORDERS_DIR}" +) + +if [ -n "${OA_SOURCES_DIR:-}" ]; then + PREPROCESSOR_ARGS+=(--oa-sources-dir "${OA_SOURCES_DIR}") +fi + +echo "Running preprocessor ..." +python3 "${PREPROCESSOR}" "${PREPROCESSOR_ARGS[@]}" + +echo "" +echo "=== Done. Output in ${OA_OUTPUT_DIR} ===" +echo "Set ADDRESSES_PATH=${OA_OUTPUT_DIR} in the [External] section of map_generator.ini" +ls -lah "${OA_OUTPUT_DIR}" | head -20