perliedman / leaflet-routing-machine

Control for routing in Leaflet
https://www.liedman.net/leaflet-routing-machine/
Other
1.08k stars 350 forks source link

Unable to get directions displayed in French or Spanish #567

Closed DevRapitow closed 4 years ago

DevRapitow commented 4 years ago

Hi

I have checked stackoverflow and the LRM docs but am unable to get the language parameter to affect any itinerary directions. They always display in English. I am using the 3.2.12 distribution with HERE maps. Everything else works very well.

I did see the https://next.plnkr.co/edit/sBPWYYMo08ijyQ6NxO0n?p=preview&preview example but that does not use a router like HERE maps. When adding the line "router: new L.Routing.Here(AppID, AppCode, routeroptions)," to the Plunker example the directions revert to English.

Any help is appreciated.

My code below: routeroptions = { serviceUrl: RESTProxyURL + 'https://route.api.here.com/routing/7.2/calculateroute.json', timeout: 30 * 1000, alternatives: 0, mode: 'fastest;car', language: 'fr', urlParameters: {} };

var uom = ((distunit == 'km') ? 'metric' : 'imperial');

maprouter = L.Routing.control({ waypoints: [sp, ep], language: 'fr', router: new L.Routing.Here(AppID, AppCode, routeroptions), show: true, autoRoute: false, addWaypoints: false, draggableWaypoints: false, routeWhileDragging: false, units: uom, reverseWaypoints: false }) .on('routingstart', function () { document.getElementById("spinner").style.display = "block"; }) .on('routesfound routingerror', function () { document.getElementById("spinner").style.display = "none"; }) .on("routeselected", function (e) { resizeSub(); }) .addTo(map); L.Routing.errorControl(maprouter).addTo(map); maprouter.route();

perliedman commented 4 years ago

Hi, I'm not familiar with the HERE plugin more than that I have seen it exists, but from a quick look at the code, it looks like the HERE backend returns the instructions text directly, which means LRM just shows whatever text the backend returns. This is means it is not a LRM issue.

If the backend has language support, you should open an issue with the HERE LRM plugin so that it supports multiple locales.

DevRapitow commented 4 years ago

Advice very appreciated. I managed to patch the lrm and the here plugin to accept here language codes.

On Wed, Jan 29, 2020 at 2:43 AM Per Liedman notifications@github.com wrote:

Hi, I'm not familiar with the HERE plugin more than that I have seen it exists, but from a quick look at the code, it looks like the HERE backend returns the instructions text directly, which means LRM just shows whatever text the backend returns. This is means it is not a LRM issue.

If the backend has language support, you should open an issue with the HERE LRM plugin so that it supports multiple locales.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/perliedman/leaflet-routing-machine/issues/567?email_source=notifications&email_token=AGNKDMXXDJ6ZSLZAHNYIJVDRAEXRPA5CNFSM4KMI6GI2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKGIILI#issuecomment-579634221, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGNKDMTS3FMRYTEJS7CDLALRAEXRPANCNFSM4KMI6GIQ .

DevRapitow commented 4 years ago

In case you are interested. English, French and Spanish only. Sorry I don't do social media:

On Wed, Jan 29, 2020 at 11:39 PM Don Youdale don@rapitow.com wrote:

Advice very appreciated. I managed to patch the lrm and the here plugin to accept here language codes.

On Wed, Jan 29, 2020 at 2:43 AM Per Liedman notifications@github.com wrote:

Hi, I'm not familiar with the HERE plugin more than that I have seen it exists, but from a quick look at the code, it looks like the HERE backend returns the instructions text directly, which means LRM just shows whatever text the backend returns. This is means it is not a LRM issue.

If the backend has language support, you should open an issue with the HERE LRM plugin so that it supports multiple locales.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/perliedman/leaflet-routing-machine/issues/567?email_source=notifications&email_token=AGNKDMXXDJ6ZSLZAHNYIJVDRAEXRPA5CNFSM4KMI6GI2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKGIILI#issuecomment-579634221, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGNKDMTS3FMRYTEJS7CDLALRAEXRPANCNFSM4KMI6GIQ .

//v1.1.0 (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ function corslite(url, callback, cors) { var sent = false;

if (typeof window.XMLHttpRequest === 'undefined') {
    return callback(Error('Browser not supported'));
}

if (typeof cors === 'undefined') {
    var m = url.match(/^\s*https?:\/\/[^\/]*/);
    cors = m && (m[0] !== location.protocol + '//' + location.domain +
            (location.port ? ':' + location.port : ''));
}

var x = new window.XMLHttpRequest();

function isSuccessful(status) {
    return status >= 200 && status < 300 || status === 304;
}

if (cors && !('withCredentials' in x)) {
    // IE8-9
    x = new window.XDomainRequest();

    // Ensure callback is never called synchronously, i.e., before
    // x.send() returns (this has been observed in the wild).
    // See https://github.com/mapbox/mapbox.js/issues/472
    var original = callback;
    callback = function() {
        if (sent) {
            original.apply(this, arguments);
        } else {
            var that = this, args = arguments;
            setTimeout(function() {
                original.apply(that, args);
            }, 0);
        }
    }
}

function loaded() {
    if (
        // XDomainRequest
        x.status === undefined ||
        // modern browsers
        isSuccessful(x.status)) callback.call(x, null, x);
    else callback.call(x, x, null);
}

// Both `onreadystatechange` and `onload` can fire. `onreadystatechange`
// has [been supported for longer](http://stackoverflow.com/a/9181508/229001).
if ('onload' in x) {
    x.onload = loaded;
} else {
    x.onreadystatechange = function readystate() {
        if (x.readyState === 4) {
            loaded();
        }
    };
}

// Call the callback with the XMLHttpRequest object as an error and prevent
// it from ever being called again by reassigning it to `noop`
x.onerror = function error(evt) {
    // XDomainRequest provides no evt parameter
    callback.call(this, evt || true, null);
    callback = function() { };
};

// IE9 must have onprogress be set to a unique function.
x.onprogress = function() { };

x.ontimeout = function(evt) {
    callback.call(this, evt, null);
    callback = function() { };
};

x.onabort = function(evt) {
    callback.call(this, evt, null);
    callback = function() { };
};

// GET is the only supported HTTP Verb by XDomainRequest and is the
// only one supported here.
x.open('GET', url, true);

// Send the request. Sending data is not supported.
x.send(null);
sent = true;

return x;

}

if (typeof module !== 'undefined') module.exports = corslite;

},{}],2:[function(require,module,exports){ // haversine // By Nick Justice (niix) // https://github.com/niix/haversine

var haversine = (function() {

// convert to radians var toRad = function(num) { return num * Math.PI / 180 }

return function haversine(start, end, options) { var km = 6371 var mile = 3960 options = options || {}

var R = options.unit === 'mile' ?
  mile :
  km

var dLat = toRad(end.latitude - start.latitude)
var dLon = toRad(end.longitude - start.longitude)
var lat1 = toRad(start.latitude)
var lat2 = toRad(end.latitude)

var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2)
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))

if (options.threshold) {
  return options.threshold > (R * c)
} else {
  return R * c
}

}

})()

module.exports = haversine },{}],3:[function(require,module,exports){ (function (global){ (function() { 'use strict';

var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null);
var corslite = require('corslite');
var haversine = require('haversine');

L.Routing = L.Routing || {};

L.Routing.Here = L.Class.extend({
    options: {
        serviceUrl: 'https://route.cit.api.here.com/routing/7.2/calculateroute.json',
        timeout: 30 * 1000,
        alternatives: 0,
        mode: 'fastest;car',
        language: 'en-us',
        urlParameters: {}
    },

    initialize: function(appId, appCode, options) {
        this._appId = appId;
        this._appCode = appCode;
        L.Util.setOptions(this, options);
    },

    route: function(waypoints, callback, context, options) {
        var timedOut = false,
            wps = [],
            url,
            timer,
            wp,
            i;

        options = options || {};
        url = this.buildRouteUrl(waypoints, options);

        timer = setTimeout(function() {
                            timedOut = true;
                            callback.call(context || callback, {
                                status: -1,
                                message: 'Here request timed out.'
                            });
                        }, this.options.timeout);

        // Create a copy of the waypoints, since they
        // might otherwise be asynchronously modified while
        // the request is being processed.
        for (i = 0; i < waypoints.length; i++) {
            wp = waypoints[i];
            wps.push({
                latLng: wp.latLng,
                name: wp.name,
                options: wp.options
            });
        }

        corslite(url, L.bind(function(err, resp) {
            var data;

            clearTimeout(timer);
            if (!timedOut) {
                if (!err) {
                    data = JSON.parse(resp.responseText);
                    this._routeDone(data, wps, callback, context);
                } else {
                    callback.call(context || callback, {
                        status: -1,
                        message: 'HTTP request failed: ' + err
                    });
                }
            }
        }, this));

        return this;
    },

    _routeDone: function(response, inputWaypoints, callback, context) {
        var alts = [],
            waypoints,
            waypoint,
            coordinates,
            i, j, k,
            instructions,
            distance,
            time,
            leg,
            maneuver,
            startingSearchIndex,
            instruction,
            path;

        context = context || callback;
        if (!response.response.route) {
            callback.call(context, {
                // TODO: include all errors
                status: response.type,
                message: response.details
            });
            return;
        }

        for (i = 0; i < response.response.route.length; i++) {
            path = response.response.route[i];
            coordinates = this._decodeGeometry(path.shape);
            startingSearchIndex = 0;

            instructions = [];
            time = 0;
            distance = 0;
            for(j = 0; j < path.leg.length; j++) {
                leg = path.leg[j];
                for(k = 0; k < leg.maneuver.length; k++) {
                    maneuver = leg.maneuver[k];
                    distance += maneuver.length;
                    time += maneuver.travelTime;
                    instruction = this._convertInstruction(maneuver, coordinates, startingSearchIndex);
                    instructions.push(instruction);
                    startingSearchIndex = instruction.index;
                }
            }

            waypoints = [];
            for(j = 0; j < path.waypoint.length; j++) {
                waypoint = path.waypoint[j];
                waypoints.push(new L.LatLng(
                    waypoint.mappedPosition.latitude, 
                    waypoint.mappedPosition.longitude));
            }

            alts.push({
                name: '',
                coordinates: coordinates,
                instructions: instructions,
                summary: {
                    totalDistance: distance,
                    totalTime: time,
                },
                inputWaypoints: inputWaypoints,
                waypoints: waypoints
            });
        }

        callback.call(context, null, alts);
    },

    _decodeGeometry: function(geometry) {
        var latlngs = new Array(geometry.length),
            coord,
            i;
        for (i = 0; i < geometry.length; i++) {
            coord = geometry[i].split(",");
            latlngs[i] = ([parseFloat(coord[0]), parseFloat(coord[1])]);
        }

        return latlngs;
    },

    buildRouteUrl: function(waypoints, options) {
        var locs = [],
            i,
            alternatives,
            baseUrl;

        for (i = 0; i < waypoints.length; i++) {
            locs.push('waypoint' + i + '=geo!' + waypoints[i].latLng.lat + ',' + waypoints[i].latLng.lng);
        }
        if(waypoints.length > 2) {
            alternatives = 0;
        } else {
            //With more than 1 waypoint, requests for alternatives are invalid
            alternatives = this.options.alternatives;
        }
        baseUrl = this.options.serviceUrl + '?' + locs.join('&');

        return baseUrl + L.Util.getParamString(L.extend({
                instructionFormat: 'text',
                app_code: this._appCode,
                app_id: this._appId,
                representation: "navigation",
                mode: this.options.mode,
                language: this.options.language,
                alternatives: alternatives
            }, this.options.urlParameters), baseUrl);
    },

    _convertInstruction: function(instruction, coordinates, startingSearchIndex) {
        var i,
        distance,
        closestDistance = 0,
        closestIndex = -1,
        coordinate = instruction.position;
        if(startingSearchIndex < 0) {
            startingSearchIndex = 0;
        }
        for(i = startingSearchIndex; i < coordinates.length; i++) {
            distance = haversine(coordinate, {latitude:coordinates[0], longitude:coordinates[1]});
            if(distance < closestDistance || closestIndex == -1) {
                closestDistance = distance;
                closestIndex = i;
            }
        }
        return {
            text: instruction.instruction,//text,
            distance: instruction.length,
            time: instruction.travelTime,
            index: closestIndex
            /*
            type: instruction.action,
            road: instruction.roadName,
            */
        };
    },

});

L.Routing.here = function(appId, appCode, options) {
    return new L.Routing.Here(appId, appCode, options);
};

module.exports = L.Routing.Here;

})();

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"corslite":1,"haversine":2}]},{},[3]);

(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(dereq,module,exports){ function corslite(url, callback, cors) { var sent = false;

if (typeof window.XMLHttpRequest === 'undefined') {
    return callback(Error('Browser not supported'));
}

if (typeof cors === 'undefined') {
    var m = url.match(/^\s*https?:\/\/[^\/]*/);
    cors = m && (m[0] !== location.protocol + '//' + location.hostname +
            (location.port ? ':' + location.port : ''));
}

var x = new window.XMLHttpRequest();

function isSuccessful(status) {
    return status >= 200 && status < 300 || status === 304;
}

if (cors && !('withCredentials' in x)) {
    // IE8-9
    x = new window.XDomainRequest();

    // Ensure callback is never called synchronously, i.e., before
    // x.send() returns (this has been observed in the wild).
    // See https://github.com/mapbox/mapbox.js/issues/472
    var original = callback;
    callback = function() {
        if (sent) {
            original.apply(this, arguments);
        } else {
            var that = this, args = arguments;
            setTimeout(function() {
                original.apply(that, args);
            }, 0);
        }
    }
}

function loaded() {
    if (
        // XDomainRequest
        x.status === undefined ||
        // modern browsers
        isSuccessful(x.status)) callback.call(x, null, x);
    else callback.call(x, x, null);
}

// Both `onreadystatechange` and `onload` can fire. `onreadystatechange`
// has [been supported for longer](http://stackoverflow.com/a/9181508/229001).
if ('onload' in x) {
    x.onload = loaded;
} else {
    x.onreadystatechange = function readystate() {
        if (x.readyState === 4) {
            loaded();
        }
    };
}

// Call the callback with the XMLHttpRequest object as an error and prevent
// it from ever being called again by reassigning it to `noop`
x.onerror = function error(evt) {
    // XDomainRequest provides no evt parameter
    callback.call(this, evt || true, null);
    callback = function() { };
};

// IE9 must have onprogress be set to a unique function.
x.onprogress = function() { };

x.ontimeout = function(evt) {
    callback.call(this, evt, null);
    callback = function() { };
};

x.onabort = function(evt) {
    callback.call(this, evt, null);
    callback = function() { };
};

// GET is the only supported HTTP Verb by XDomainRequest and is the
// only one supported here.
x.open('GET', url, true);

// Send the request. Sending data is not supported.
x.send(null);
sent = true;

return x;

}

if (typeof module !== 'undefined') module.exports = corslite;

},{}],2:[function(dereq,module,exports){ 'use strict';

/**

var polyline = {};

function py2_round(value) { // Google's polyline algorithm uses the same rounding strategy as Python 2, which is different from JS for negative values return Math.floor(Math.abs(value) + 0.5) * Math.sign(value); }

function encode(current, previous, factor) { current = py2_round(current factor); previous = py2_round(previous factor); var coordinate = current - previous; coordinate <<= 1; if (current - previous < 0) { coordinate = ~coordinate; } var output = ''; while (coordinate >= 0x20) { output += String.fromCharCode((0x20 | (coordinate & 0x1f)) + 63); coordinate >>= 5; } output += String.fromCharCode(coordinate + 63); return output; }

/**

/**

function flipped(coords) { var flipped = []; for (var i = 0; i < coords.length; i++) { flipped.push(coords[i].slice().reverse()); } return flipped; }

/**

/**

if (typeof module === 'object' && module.exports) { module.exports = polyline; }

},{}],3:[function(dereq,module,exports){ var languages = dereq('./languages'); var instructions = languages.instructions; var grammars = languages.grammars; var abbreviations = languages.abbreviations;

module.exports = function(version) { Object.keys(instructions).forEach(function(code) { if (!instructions[code][version]) { throw 'invalid version ' + version + ': ' + code + ' not supported'; } });

return {
    capitalizeFirstLetter: function(language, string) {
        return string.charAt(0).toLocaleUpperCase(language) + string.slice(1);
    },
    ordinalize: function(language, number) {
        // Transform numbers to their translated ordinalized value
        if (!language) throw new Error('No language code provided');

        return instructions[language][version].constants.ordinalize[number.toString()] || '';
    },
    directionFromDegree: function(language, degree) {
        // Transform degrees to their translated compass direction
        if (!language) throw new Error('No language code provided');
        if (!degree && degree !== 0) {
            // step had no bearing_after degree, ignoring
            return '';
        } else if (degree >= 0 && degree <= 20) {
            return instructions[language][version].constants.direction.north;
        } else if (degree > 20 && degree < 70) {
            return instructions[language][version].constants.direction.northeast;
        } else if (degree >= 70 && degree <= 110) {
            return instructions[language][version].constants.direction.east;
        } else if (degree > 110 && degree < 160) {
            return instructions[language][version].constants.direction.southeast;
        } else if (degree >= 160 && degree <= 200) {
            return instructions[language][version].constants.direction.south;
        } else if (degree > 200 && degree < 250) {
            return instructions[language][version].constants.direction.southwest;
        } else if (degree >= 250 && degree <= 290) {
            return instructions[language][version].constants.direction.west;
        } else if (degree > 290 && degree < 340) {
            return instructions[language][version].constants.direction.northwest;
        } else if (degree >= 340 && degree <= 360) {
            return instructions[language][version].constants.direction.north;
        } else {
            throw new Error('Degree ' + degree + ' invalid');
        }
    },
    laneConfig: function(step) {
        // Reduce any lane combination down to a contracted lane diagram
        if (!step.intersections || !step.intersections[0].lanes) throw new Error('No lanes object');

        var config = [];
        var currentLaneValidity = null;

        step.intersections[0].lanes.forEach(function (lane) {
            if (currentLaneValidity === null || currentLaneValidity !== lane.valid) {
                if (lane.valid) {
                    config.push('o');
                } else {
                    config.push('x');
                }
                currentLaneValidity = lane.valid;
            }
        });

        return config.join('');
    },
    getWayName: function(language, step, options) {
        var classes = options ? options.classes || [] : [];
        if (typeof step !== 'object') throw new Error('step must be an Object');
        if (!language) throw new Error('No language code provided');
        if (!Array.isArray(classes)) throw new Error('classes must be an Array or undefined');

        var wayName;
        var name = step.name || '';
        var ref = (step.ref || '').split(';')[0];

        // Remove hacks from Mapbox Directions mixing ref into name
        if (name === step.ref) {
            // if both are the same we assume that there used to be an empty name, with the ref being filled in for it
            // we only need to retain the ref then
            name = '';
        }
        name = name.replace(' (' + step.ref + ')', '');

        // In attempt to avoid using the highway name of a way,
        // check and see if the step has a class which should signal
        // the ref should be used instead of the name.
        var wayMotorway = classes.indexOf('motorway') !== -1;

        if (name && ref && name !== ref && !wayMotorway) {
            var phrase = instructions[language][version].phrase['name and ref'] ||
                instructions.en[version].phrase['name and ref'];
            wayName = this.tokenize(language, phrase, {
                name: name,
                ref: ref
            }, options);
        } else if (name && ref && wayMotorway && (/\d/).test(ref)) {
            wayName = options && options.formatToken ? options.formatToken('ref', ref) : ref;
        } else if (!name && ref) {
            wayName = options && options.formatToken ? options.formatToken('ref', ref) : ref;
        } else {
            wayName = options && options.formatToken ? options.formatToken('name', name) : name;
        }

        return wayName;
    },

    /**
     * Formulate a localized text instruction from a step.
     *
     * @param  {string} language           Language code.
     * @param  {object} step               Step including maneuver property.
     * @param  {object} opts               Additional options.
     * @param  {string} opts.legIndex      Index of leg in the route.
     * @param  {string} opts.legCount      Total number of legs in the route.
     * @param  {array}  opts.classes       List of road classes.
     * @param  {string} opts.waypointName  Name of waypoint for arrival instruction.
     *
     * @return {string} Localized text instruction.
     */
    compile: function(language, step, opts) {
        if (!language) throw new Error('No language code provided');
        if (languages.supportedCodes.indexOf(language) === -1) throw new Error('language code ' + language + ' not loaded');
        if (!step.maneuver) throw new Error('No step maneuver provided');
        var options = opts || {};

        var type = step.maneuver.type;
        var modifier = step.maneuver.modifier;
        var mode = step.mode;
        // driving_side will only be defined in OSRM 5.14+
        var side = step.driving_side;

        if (!type) { throw new Error('Missing step maneuver type'); }
        if (type !== 'depart' && type !== 'arrive' && !modifier) { throw new Error('Missing step maneuver modifier'); }

        if (!instructions[language][version][type]) {
            // Log for debugging
            console.log('Encountered unknown instruction type: ' + type); // eslint-disable-line no-console
            // OSRM specification assumes turn types can be added without
            // major version changes. Unknown types are to be treated as
            // type `turn` by clients
            type = 'turn';
        }

        // Use special instructions if available, otherwise `defaultinstruction`
        var instructionObject;
        if (instructions[language][version].modes[mode]) {
            instructionObject = instructions[language][version].modes[mode];
        } else {
          // omit side from off ramp if same as driving_side
          // note: side will be undefined if the input is from OSRM <5.14
          // but the condition should still evaluate properly regardless
            var omitSide = type === 'off ramp' && modifier.indexOf(side) >= 0;
            if (instructions[language][version][type][modifier] && !omitSide) {
                instructionObject = instructions[language][version][type][modifier];
            } else {
                instructionObject = instructions[language][version][type].default;
            }
        }

        // Special case handling
        var laneInstruction;
        switch (type) {
        case 'use lane':
            laneInstruction = instructions[language][version].constants.lanes[this.laneConfig(step)];
            if (!laneInstruction) {
                // If the lane combination is not found, default to continue straight
                instructionObject = instructions[language][version]['use lane'].no_lanes;
            }
            break;
        case 'rotary':
        case 'roundabout':
            if (step.rotary_name && step.maneuver.exit && instructionObject.name_exit) {
                instructionObject = instructionObject.name_exit;
            } else if (step.rotary_name && instructionObject.name) {
                instructionObject = instructionObject.name;
            } else if (step.maneuver.exit && instructionObject.exit) {
                instructionObject = instructionObject.exit;
            } else {
                instructionObject = instructionObject.default;
            }
            break;
        default:
            // NOOP, since no special logic for that type
        }

        // Decide way_name with special handling for name and ref
        var wayName = this.getWayName(language, step, options);

        // Decide which instruction string to use
        // Destination takes precedence over name
        var instruction;
        if (step.destinations && step.exits && instructionObject.exit_destination) {
            instruction = instructionObject.exit_destination;
        } else if (step.destinations && instructionObject.destination) {
            instruction = instructionObject.destination;
        } else if (step.exits && instructionObject.exit) {
            instruction = instructionObject.exit;
        } else if (wayName && instructionObject.name) {
            instruction = instructionObject.name;
        } else if (options.waypointName && instructionObject.named) {
            instruction = instructionObject.named;
        } else {
            instruction = instructionObject.default;
        }

        var destinations = step.destinations && step.destinations.split(': ');
        var destinationRef = destinations && destinations[0].split(',')[0];
        var destination = destinations && destinations[1] && destinations[1].split(',')[0];
        var firstDestination;
        if (destination && destinationRef) {
            firstDestination = destinationRef + ': ' + destination;
        } else {
            firstDestination = destinationRef || destination || '';
        }

        var nthWaypoint = options.legIndex >= 0 && options.legIndex !== options.legCount - 1 ? this.ordinalize(language, options.legIndex + 1) : '';

        // Replace tokens
        // NOOP if they don't exist
        var replaceTokens = {
            'way_name': wayName,
            'destination': firstDestination,
            'exit': (step.exits || '').split(';')[0],
            'exit_number': this.ordinalize(language, step.maneuver.exit || 1),
            'rotary_name': step.rotary_name,
            'lane_instruction': laneInstruction,
            'modifier': instructions[language][version].constants.modifier[modifier],
            'direction': this.directionFromDegree(language, step.maneuver.bearing_after),
            'nth': nthWaypoint,
            'waypoint_name': options.waypointName
        };

        return this.tokenize(language, instruction, replaceTokens, options);
    },
    grammarize: function(language, name, grammar) {
        if (!language) throw new Error('No language code provided');
        // Process way/rotary name with applying grammar rules if any
        if (name && grammar && grammars && grammars[language] && grammars[language][version]) {
            var rules = grammars[language][version][grammar];
            if (rules) {
                // Pass original name to rules' regular expressions enclosed with spaces for simplier parsing
                var n = ' ' + name + ' ';
                var flags = grammars[language].meta.regExpFlags || '';
                rules.forEach(function(rule) {
                    var re = new RegExp(rule[0], flags);
                    n = n.replace(re, rule[1]);
                });

                return n.trim();
            }
        }

        return name;
    },
    abbreviations: abbreviations,
    tokenize: function(language, instruction, tokens, options) {
        if (!language) throw new Error('No language code provided');
        // Keep this function context to use in inline function below (no arrow functions in ES4)
        var that = this;
        var startedWithToken = false;
        var output = instruction.replace(/\{(\w+)(?::(\w+))?\}/g, function(token, tag, grammar, offset) {
            var value = tokens[tag];

            // Return unknown token unchanged
            if (typeof value === 'undefined') {
                return token;
            }

            value = that.grammarize(language, value, grammar);

            // If this token appears at the beginning of the instruction, capitalize it.
            if (offset === 0 && instructions[language].meta.capitalizeFirstLetter) {
                startedWithToken = true;
                value = that.capitalizeFirstLetter(language, value);
            }

            if (options && options.formatToken) {
                value = options.formatToken(tag, value);
            }

            return value;
        })
        .replace(/ {2}/g, ' '); // remove excess spaces

        if (!startedWithToken && instructions[language].meta.capitalizeFirstLetter) {
            return this.capitalizeFirstLetter(language, output);
        }

        return output;
    }
};

};

},{"./languages":4}],4:[function(dereq,module,exports){ // Load all language files explicitly to allow integration // with bundling tools like webpack and browserify var instructionsDa = dereq('./languages/translations/da.json'); var instructionsDe = dereq('./languages/translations/de.json'); var instructionsEn = dereq('./languages/translations/en.json'); var instructionsEo = dereq('./languages/translations/eo.json'); var instructionsEs = dereq('./languages/translations/es.json'); var instructionsEsEs = dereq('./languages/translations/es-ES.json'); var instructionsFi = dereq('./languages/translations/fi.json'); var instructionsFr = dereq('./languages/translations/fr.json'); var instructionsHe = dereq('./languages/translations/he.json'); var instructionsId = dereq('./languages/translations/id.json'); var instructionsIt = dereq('./languages/translations/it.json'); var instructionsKo = dereq('./languages/translations/ko.json'); var instructionsMy = dereq('./languages/translations/my.json'); var instructionsNl = dereq('./languages/translations/nl.json'); var instructionsNo = dereq('./languages/translations/no.json'); var instructionsPl = dereq('./languages/translations/pl.json'); var instructionsPtBr = dereq('./languages/translations/pt-BR.json'); var instructionsPtPt = dereq('./languages/translations/pt-PT.json'); var instructionsRo = dereq('./languages/translations/ro.json'); var instructionsRu = dereq('./languages/translations/ru.json'); var instructionsSv = dereq('./languages/translations/sv.json'); var instructionsTr = dereq('./languages/translations/tr.json'); var instructionsUk = dereq('./languages/translations/uk.json'); var instructionsVi = dereq('./languages/translations/vi.json'); var instructionsZhHans = dereq('./languages/translations/zh-Hans.json');

// Load all grammar files var grammarFr = dereq('./languages/grammar/fr.json'); var grammarRu = dereq('./languages/grammar/ru.json');

// Load all abbreviations files var abbreviationsBg = dereq('./languages/abbreviations/bg.json'); var abbreviationsCa = dereq('./languages/abbreviations/ca.json'); var abbreviationsDa = dereq('./languages/abbreviations/da.json'); var ebbreviationsDe = dereq('./languages/abbreviations/de.json'); var abbreviationsEn = dereq('./languages/abbreviations/en.json'); var abbreviationsEs = dereq('./languages/abbreviations/es.json'); var abbreviationsFr = dereq('./languages/abbreviations/fr.json'); var abbreviationsHe = dereq('./languages/abbreviations/he.json'); var abbreviationsHu = dereq('./languages/abbreviations/hu.json'); var abbreviationsLt = dereq('./languages/abbreviations/lt.json'); var abbreviationsNl = dereq('./languages/abbreviations/nl.json'); var abbreviationsRu = dereq('./languages/abbreviations/ru.json'); var abbreviationsSl = dereq('./languages/abbreviations/sl.json'); var abbreviationsSv = dereq('./languages/abbreviations/sv.json'); var abbreviationsUk = dereq('./languages/abbreviations/uk.json'); var abbreviationsVi = dereq('./languages/abbreviations/vi.json');

// Create a list of supported codes var instructions = { 'da': instructionsDa, 'de': instructionsDe, 'en': instructionsEn, 'en-us': instructionsEn, 'eo': instructionsEo, 'es': instructionsEs, 'es-ES': instructionsEsEs, 'fi': instructionsFi, 'fr': instructionsFr, 'fr-fr': instructionsFr, 'he': instructionsHe, 'id': instructionsId, 'it': instructionsIt, 'ko': instructionsKo, 'my': instructionsMy, 'nl': instructionsNl, 'no': instructionsNo, 'pl': instructionsPl, 'pt-BR': instructionsPtBr, 'pt-PT': instructionsPtPt, 'ro': instructionsRo, 'ru': instructionsRu, 'sv': instructionsSv, 'tr': instructionsTr, 'uk': instructionsUk, 'vi': instructionsVi, 'zh-Hans': instructionsZhHans };

// Create list of supported grammar var grammars = { 'fr': grammarFr, 'fr-fr': grammarFr, 'ru': grammarRu };

// Create list of supported abbrevations var abbreviations = { 'bg': abbreviationsBg, 'ca': abbreviationsCa, 'da': abbreviationsDa, 'de': ebbreviationsDe, 'en': abbreviationsEn, 'en-us': abbreviationsEn, 'es': abbreviationsEs, 'fr': abbreviationsFr, 'fr-fr': abbreviationsFr, 'he': abbreviationsHe, 'hu': abbreviationsHu, 'lt': abbreviationsLt, 'nl': abbreviationsNl, 'ru': abbreviationsRu, 'sl': abbreviationsSl, 'sv': abbreviationsSv, 'uk': abbreviationsUk, 'vi': abbreviationsVi }; module.exports = { supportedCodes: Object.keys(instructions), instructions: instructions, grammars: grammars, abbreviations: abbreviations };

},{"./languages/abbreviations/bg.json":5,"./languages/abbreviations/ca.json":6,"./languages/abbreviations/da.json":7,"./languages/abbreviations/de.json":8,"./languages/abbreviations/en.json":9,"./languages/abbreviations/es.json":10,"./languages/abbreviations/fr.json":11,"./languages/abbreviations/he.json":12,"./languages/abbreviations/hu.json":13,"./languages/abbreviations/lt.json":14,"./languages/abbreviations/nl.json":15,"./languages/abbreviations/ru.json":16,"./languages/abbreviations/sl.json":17,"./languages/abbreviations/sv.json":18,"./languages/abbreviations/uk.json":19,"./languages/abbreviations/vi.json":20,"./languages/grammar/fr.json":21,"./languages/grammar/ru.json":22,"./languages/translations/da.json":23,"./languages/translations/de.json":24,"./languages/translations/en.json":25,"./languages/translations/eo.json":26,"./languages/translations/es-ES.json":27,"./languages/translations/es.json":28,"./languages/translations/fi.json":29,"./languages/translations/fr.json":30,"./languages/translations/he.json":31,"./languages/translations/id.json":32,"./languages/translations/it.json":33,"./languages/translations/ko.json":34,"./languages/translations/my.json":35,"./languages/translations/nl.json":36,"./languages/translations/no.json":37,"./languages/translations/pl.json":38,"./languages/translations/pt-BR.json":39,"./languages/translations/pt-PT.json":40,"./languages/translations/ro.json":41,"./languages/translations/ru.json":42,"./languages/translations/sv.json":43,"./languages/translations/tr.json":44,"./languages/translations/uk.json":45,"./languages/translations/vi.json":46,"./languages/translations/zh-Hans.json":47}],5:[function(dereq,module,exports){ module.exports={ "abbreviations": { "международен": "Межд", "старши": "Стрш", "възел": "Въз", "пазар": "Mkt", "светисвети": "СвСв", "сестра": "сес", "уилям": "Ум", "апартаменти": "ап", "езеро": "Ез", "свети": "Св", "център": "Ц-р", "парк": "Пк", "маршрут": "М-т", "площад": "Пл", "национален": "Нац", "училище": "Уч", "река": "Рек", "поток": "П-к", "район": "Р-н", "крепост": "К-т", "паметник": "Пам", "университет": "Уни", "Връх": "Вр", "точка": "Точ", "планина": "Пл", "село": "с.", "височини": "вис", "младши": "Мл", "станция": "С-я", "проход": "Прох", "баща": "Бщ" }, "classifications": { "шофиране": "Шоф", "плавен": "Пл", "място": "Мя", "тераса": "Тер", "магистрала": "М-ла", "площад": "Пл", "пеш": "Пеш", "залив": "З-в", "пътека": "П-ка", "платно": "Пл", "улица": "Ул", "алея": "Ал", "пешеходна": "Пеш", "точка": "Тч", "задминаване": "Задм", "кръгово": "Кр", "връх": "Вр", "съд": "Сд", "булевард": "Бул", "път": "Път", "скоростна": "Скор", "мост": "Мо" }, "directions": { "северозапад": "СЗ", "североизток": "СИ", "югозапад": "ЮЗ", "югоизток": "ЮИ", "север": "С", "изток": "И", "юг": "Ю" } }

},{}],6:[function(dereq,module,exports){ module.exports={ "abbreviations": { "comunicacions": "Com.", "entitat de població": "Nucli", "disseminat": "Diss.", "cap de municipi": "Cap", "indret": "Indr.", "comarca": "Cca.", "relleu del litoral": "Lit.", "municipi": "Mun.", "xarxa hidrogràfica": "Curs Fluv.", "equipament": "Equip.", "orografia": "Orogr.", "barri": "Barri", "edificació": "Edif.", "edificació històrica": "Edif. Hist.", "entitat descentralitzada": "E.M.D.", "element hidrogràfic": "Hidr." }, "classifications": { "rotonda": "Rot.", "carrerada": "Ca.", "jardí": "J.", "paratge": "Pge.", "pont": "Pont", "lloc": "Lloc", "rambla": "Rbla.", "cases": "Cses.", "barranc": "Bnc.", "plana": "Plana", "polígon": "Pol.", "muralla": "Mur.", "enllaç": "Ellaç", "antiga carretera": "Actra", "glorieta": "Glor.", "autovia": "Autv.", "prolongació": "Prol.", "calçada": "Cda.", "carretera": "Ctra.", "pujada": "Pda.", "torrent": "T.", "disseminat": "Disse", "barri": "B.", "cinturó": "Cinto", "passera": "Psera", "sender": "Send.", "carrer": "C.", "sèquia": "Sèq.", "blocs": "Bloc", "rambleta": "Rblt.", "partida": "Par.", "costa": "Cos.", "sector": "Sec.", "corraló": "Crral", "urbanització": "Urb.", "autopista": "Autp.", "grup": "Gr.", "platja": "Pja.", "jardins": "J.", "complex": "Comp.", "portals": "Ptals", "finca": "Fin.", "travessera": "Trav.", "plaça": "Pl.", "travessia": "Trv.", "polígon industrial": "PI.", "passatge": "Ptge.", "apartaments": "Apmt.", "mirador": "Mira.", "antic": "Antic", "accés": "Acc.", "colònia": "Col.", "corriol": "Crol.", "portal": "Ptal.", "porta": "Pta.", "port": "Port", "carreró": "Cró.", "riera": "Ra.", "circumval·lació": "Cval.", "baixada": "Bda.", "placeta": "Plta.", "escala": "Esc.", "gran via": "GV", "rial": "Rial", "conjunt": "Conj.", "avinguda": "Av.", "esplanada": "Esp.", "cantonada": "Cant.", "ronda": "Rda.", "corredor": "Cdor.", "drecera": "Drec.", "passadís": "Pdís.", "viaducte": "Vdct.", "passeig": "Pg.", "veïnat": "Veï." }, "directions": { "sudest": "SE", "sudoest": "SO", "nordest": "NE", "nordoest": "NO", "est": "E", "nord": "N", "oest": "O", "sud": "S" } }

},{}],7:[function(dereq,module,exports){ module.exports={ "abbreviations": { "skole": "Sk.", "ved": "v.", "centrum": "C.", "sankt": "Skt.", "vestre": "v.", "hospital": "Hosp.", "stræde": "Str.", "nordre": "Nr.", "plads": "Pl.", "universitet": "Uni.", "vænge": "vg.", "station": "St." }, "classifications": { "avenue": "Ave", "gammel": "Gl.", "dronning": "Dronn.", "sønder": "Sdr.", "nørre": "Nr.", "vester": "V.", "vestre": "V.", "øster": "Ø.", "østre": "Ø.", "boulevard": "Boul." }, "directions": { "sydøst": "SØ", "nordvest": "NV", "syd": "S", "nordøst": "NØ", "sydvest": "SV", "vest": "V", "nord": "N", "øst": "Ø" } }

},{}],8:[function(dereq,module,exports){ module.exports={ "abbreviations": {}, "classifications": {}, "directions": { "osten": "O", "nordosten": "NO", "süden": "S", "nordwest": "NW", "norden": "N", "südost": "SO", "südwest": "SW", "westen": "W" } }

},{}],9:[function(dereq,module,exports){ module.exports={ "abbreviations": { "square": "Sq", "centre": "Ctr", "sister": "Sr", "lake": "Lk", "fort": "Ft", "route": "Rte", "william": "Wm", "national": "Nat’l", "junction": "Jct", "center": "Ctr", "saint": "St", "saints": "SS", "station": "Sta", "mount": "Mt", "junior": "Jr", "mountain": "Mtn", "heights": "Hts", "university": "Univ", "school": "Sch", "international": "Int’l", "apartments": "Apts", "crossing": "Xing", "creek": "Crk", "township": "Twp", "downtown": "Dtwn", "father": "Fr", "senior": "Sr", "point": "Pt", "river": "Riv", "market": "Mkt", "village": "Vil", "park": "Pk", "memorial": "Mem" }, "classifications": { "place": "Pl", "circle": "Cir", "bypass": "Byp", "motorway": "Mwy", "crescent": "Cres", "road": "Rd", "cove": "Cv", "lane": "Ln", "square": "Sq", "street": "St", "freeway": "Fwy", "walk": "Wk", "plaza": "Plz", "parkway": "Pky", "avenue": "Ave", "pike": "Pk", "drive": "Dr", "highway": "Hwy", "footway": "Ftwy", "point": "Pt", "court": "Ct", "terrace": "Ter", "walkway": "Wky", "alley": "Aly", "expressway": "Expy", "bridge": "Br", "boulevard": "Blvd", "turnpike": "Tpk" }, "directions": { "southeast": "SE", "northwest": "NW", "south": "S", "west": "W", "southwest": "SW", "north": "N", "east": "E", "northeast": "NE" } }

},{}],10:[function(dereq,module,exports){ module.exports={ "abbreviations": { "segunda": "2ª", "octubre": "8bre", "doctores": "Drs", "doctora": "Dra", "internacional": "Intl", "doctor": "Dr", "segundo": "2º", "señorita": "Srta", "doctoras": "Drs", "primera": "1ª", "primero": "1º", "san": "S", "colonia": "Col", "doña": "Dña", "septiembre": "7bre", "diciembre": "10bre", "señor": "Sr", "ayuntamiento": "Ayto", "señora": "Sra", "tercera": "3ª", "tercero": "3º", "don": "D", "santa": "Sta", "ciudad": "Cdad", "noviembre": "9bre", "departamento": "Dep" }, "classifications": { "camino": "Cmno", "avenida": "Av", "paseo": "Pº", "autopista": "Auto", "calle": "C", "plaza": "Pza", "carretera": "Crta" }, "directions": { "este": "E", "noreste": "NE", "sur": "S", "suroeste": "SO", "noroeste": "NO", "oeste": "O", "sureste": "SE", "norte": "N" } }

},{}],11:[function(dereq,module,exports){ module.exports={ "abbreviations": { "allée": "All", "aérodrome": "Aérod", "aéroport": "Aérop" }, "classifications": { "centrale": "Ctrale", "campings": "Camp.", "urbains": "Urb.", "mineure": "Min.", "publique": "Publ.", "supérieur": "Sup.", "fédération": "Féd.", "notre-dame": "ND", "saint": "St", "centre hospitalier régional": "CHR", "exploitation": "Exploit.", "général": "Gal", "civiles": "Civ.", "maritimes": "Marit.", "aviation": "Aviat.", "iii": "3", "archéologique": "Archéo.", "musical": "Music.", "musicale": "Music.", "immeuble": "Imm.", "xv": "15", "hôtel": "Hôt.", "alpine": "Alp.", "communale": "Commun.", "v": "5", "global": "Glob.", "université": "Univ.", "confédéral": "Conféd.", "xx": "20", "x": "10", "piscine": "Pisc.", "dimanche": "di.", "fleuve": "Flv", "postaux": "Post.", "musicienne": "Music.", "département": "Dépt", "février": "Févr.", "municipales": "Munic.", "province": "Prov.", "communautés": "Commtés", "barrage": "Barr.", "mercredi": "me.", "présidentes": "Pdtes", "cafétérias": "Cafét.", "théâtral": "Thé.", "viticulteur": "Vitic.", "poste": "Post.", "spécialisée": "Spéc.", "agriculture": "Agric.", "infirmier": "Infirm.", "animation": "Anim.", "mondiale": "Mond.", "arrêt": "Arr.", "zone": "zon.", "municipaux": "Munic.", "grand": "Gd", "janvier": "Janv.", "fondateur": "Fond.", "première": "1re", "municipale": "Munic.", "direction": "Dir.", "anonyme": "Anon.", "départementale": "Dépt", "moyens": "Moy.", "novembre": "Nov.", "jardin": "Jard.", "petites": "Pet.", "privé": "Priv.", "centres": "Ctres", "forestier": "Forest.", "xiv": "14", "africaines": "Afric.", "sergent": "Sgt", "européenne": "Eur.", "privée": "Priv.", "café": "Cfé", "xix": "19", "hautes": "Htes", "major": "Mjr", "vendredi": "ve.", "municipalité": "Munic.", "sous-préfecture": "Ss-préf.", "spéciales": "Spéc.", "secondaires": "Second.", "viie": "7e", "moyenne": "Moy.", "commerciale": "Commerc.", "région": "Rég.", "américaines": "Amér.", "américains": "Amér.", "service": "Sce", "professeur": "Prof.", "départemental": "Dépt", "hôtels": "Hôt.", "mondiales": "Mond.", "ire": "1re", "caporal": "Capo.", "militaire": "Milit.", "lycée d'enseignement professionnel": "LEP", "adjudant": "Adj.", "médicale": "Méd.", "conférences": "Confér.", "universelle": "Univ.", "xiie": "12e", "supérieures": "Sup.", "naturel": "Natur.", "société nationale": "SN", "hospitalier": "Hosp.", "culturelle": "Cult.", "américain": "Amér.", "son altesse royale": "S.A.R.", "infirmière": "Infirm.", "viii": "8", "fondatrice": "Fond.", "madame": "Mme", "métropolitain": "Métrop.", "ophtalmologues": "Ophtalmos", "xviie": "18e", "viiie": "8e", "commerçante": "Commerç.", "centre d'enseignement du second degré": "CES", "septembre": "Sept.", "agriculteur": "Agric.", "xiii": "13", "pontifical": "Pontif.", "cafétéria": "Cafét.", "prince": "Pce", "vie": "6e", "archiduchesse": "Archid.", "occidental": "Occ.", "spectacles": "Spect.", "camping": "Camp.", "métro": "Mº", "arrondissement": "Arrond.", "viticole": "Vitic.", "ii": "2", "siècle": "Si.", "chapelles": "Chap.", "centre": "Ctre", "sapeur-pompiers": "Sap.-pomp.", "établissements": "Étabts", "société anonyme": "SA", "directeurs": "Dir.", "vii": "7", "culturel": "Cult.", "central": "Ctral", "métropolitaine": "Métrop.", "administrations": "Admin.", "amiraux": "Amir.", "sur": "s/", "premiers": "1ers", "provence-alpes-côte d'azur": "PACA", "cathédrale": "Cathéd.", "iv": "4", "postale": "Post.", "social": "Soc.", "spécialisé": "Spéc.", "district": "Distr.", "technologique": "Techno.", "viticoles": "Vitic.", "ix": "9", "protégés": "Prot.", "historiques": "Hist.", "sous": "s/s", "national": "Nal", "ambassade": "Amb.", "cafés": "Cfés", "agronomie": "Agro.", "sapeurs": "Sap.", "petits": "Pet.", "monsieur": "M.", "boucher": "Bouch.", "restaurant": "Restau.", "lycée": "Lyc.", "urbaine": "Urb.", "préfecture": "Préf.", "districts": "Distr.", "civil": "Civ.", "protégées": "Prot.", "sapeur": "Sap.", "théâtre": "Thé.", "collège": "Coll.", "mardi": "ma.", "mémorial": "Mémor.", "africain": "Afric.", "républicaine": "Républ.", "sociale": "Soc.", "spécial": "Spéc.", "technologie": "Techno.", "charcuterie": "Charc.", "commerces": "Commerc.", "fluviale": "Flv", "parachutistes": "Para.", "primaires": "Prim.", "directions": "Dir.", "présidentiel": "Pdtl", "nationales": "Nales", "après": "apr.", "samedi": "sa.", "unité": "U.", "xxiii": "23", "associé": "Assoc.", "électrique": "Électr.", "populaire": "Pop.", "asiatique": "Asiat.", "navigable": "Navig.", "présidente": "Pdte", "xive": "14e", "associés": "Assoc.", "pompiers": "Pomp.", "agricoles": "Agric.", "élém": "Élém.", "décembre": "Déc.", "son altesse": "S.Alt.", "après-midi": "a.-m.", "mineures": "Min.", "juillet": "Juil.", "aviatrices": "Aviat.", "fondation": "Fond.", "pontificaux": "Pontif.", "temple": "Tple", "européennes": "Eur.", "régionale": "Rég.", "informations": "Infos", "mondiaux": "Mond.", "infanterie": "Infant.", "archéologie": "Archéo.", "dans": "d/", "hospice": "Hosp.", "spectacle": "Spect.", "hôtels-restaurants": "Hôt.-Rest.", "hôtel-restaurant": "Hôt.-Rest.", "hélicoptère": "hélico", "xixe": "19e", "cliniques": "Clin.", "docteur": "Dr", "secondaire": "Second.", "municipal": "Munic.", "générale": "Gale", "château": "Chât.", "commerçant": "Commerç.", "avril": "Avr.", "clinique": "Clin.", "urbaines": "Urb.", "navale": "Nav.", "navigation": "Navig.", "asiatiques": "Asiat.", "pontificales": "Pontif.", "administrative": "Admin.", "syndicat": "Synd.", "lundi": "lu.", "petite": "Pet.", "maritime": "Marit.", "métros": "Mº", "enseignement": "Enseign.", "fluviales": "Flv", "historique": "Hist.", "comtés": "Ctés", "résidentiel": "Résid.", "international": "Int.", "supérieure": "Sup.", "centre hospitalier universitaire": "CHU", "confédération": "Conféd.", "boucherie": "Bouch.", "fondatrices": "Fond.", "médicaux": "Méd.", "européens": "Eur.", "orientaux": "Ori.", "naval": "Nav.", "étang": "Étg", "provincial": "Prov.", "junior": "Jr", "départementales": "Dépt", "musique": "Musiq.", "directrices": "Dir.", "maréchal": "Mal", "civils": "Civ.", "protégé": "Prot.", "établissement": "Étabt", "trafic": "Traf.", "aviateur": "Aviat.", "archives": "Arch.", "africains": "Afric.", "maternelle": "Matern.", "industrielle": "Ind.", "administratif": "Admin.", "oriental": "Ori.", "universitaire": "Univ.", "majeur": "Maj.", "haute": "Hte", "communal": "Commun.", "petit": "Pet.", "commune": "Commun.", "exploitant": "Exploit.", "conférence": "Confér.", "monseigneur": "Mgr", "pharmacien": "Pharm.", "jeudi": "je.", "primaire": "Prim.", "hélicoptères": "hélicos", "agronomique": "Agro.", "médecin": "Méd.", "ve": "5e", "pontificale": "Pontif.", "ier": "1er", "cinéma": "Ciné", "fluvial": "Flv", "occidentaux": "Occ.", "commerçants": "Commerç.", "banque": "Bq", "moyennes": "Moy.", "pharmacienne": "Pharm.", "démocratique": "Dém.", "cinémas": "Cinés", "spéciale": "Spéc.", "présidents": "Pdts", "directrice": "Dir.", "vi": "6", "basse": "Bas.", "xve": "15e", "état": "É.", "aviateurs": "Aviat.", "majeurs": "Maj.", "infirmiers": "Infirm.", "église": "Égl.", "confédérale": "Conféd.", "xxie": "21e", "comte": "Cte", "européen": "Eur.", "union": "U.", "pharmacie": "Pharm.", "infirmières": "Infirm.", "comté": "Cté", "sportive": "Sport.", "deuxième": "2e", "xvi": "17", "haut": "Ht", "médicales": "Méd.", "développé": "Dévelop.", "bâtiment": "Bât.", "commerce": "Commerc.", "ive": "4e", "associatif": "Assoc.", "rural": "Rur.", "cimetière": "Cim.", "régional": "Rég.", "ferroviaire": "Ferr.", "vers": "v/", "mosquée": "Mosq.", "mineurs": "Min.", "nautique": "Naut.", "châteaux": "Chât.", "sportif": "Sport.", "mademoiselle": "Mle", "école": "Éc.", "doyen": "Doy.", "industriel": "Ind.", "chapelle": "Chap.", "sociétés": "Stés", "internationale": "Int.", "coopératif": "Coop.", "hospices": "Hosp.", "xxii": "22", "parachutiste": "Para.", "alpines": "Alp.", "civile": "Civ.", "xvie": "17e", "états": "É.", "musée": "Msée", "centrales": "Ctrales", "globaux": "Glob.", "supérieurs": "Sup.", "syndicats": "Synd.", "archevêque": "Archev.", "docteurs": "Drs", "bibliothèque": "Biblio.", "lieutenant": "Lieut.", "république": "Rép.", "vétérinaire": "Vét.", "départementaux": "Dépt", "premier": "1er", "fluviaux": "Flv", "animé": "Anim.", "orientales": "Ori.", "technologiques": "Techno.", "princesse": "Pse", "routière": "Rout.", "coopérative": "Coop.", "scolaire": "Scol.", "écoles": "Éc.", "football": "Foot", "territoriale": "Territ.", "commercial": "Commerc.", "mineur": "Min.", "millénaires": "Mill.", "association": "Assoc.", "catholique": "Cathol.", "administration": "Admin.", "mairie": "Mair.", "portuaire": "Port.", "tertiaires": "Terti.", "théâtrale": "Thé.", "palais": "Pal.", "troisième": "3e", "directeur": "Dir.", "vétérinaires": "Vét.", "faculté": "Fac.", "occidentales": "Occ.", "viticulteurs": "Vitic.", "xvii": "18", "occidentale": "Occ.", "amiral": "Amir.", "professionnel": "Profess.", "administratives": "Admin.", "commerciales": "Commerc.", "saints": "Sts", "agronomes": "Agro.", "stade": "Std", "sous-préfet": "Ss-préf.", "senior": "Sr", "agronome": "Agro.", "terrain": "Terr.", "catholiques": "Cathol.", "résidentielle": "Résid.", "grands": "Gds", "exploitants": "Exploit.", "xiiie": "13e", "croix": "Cx", "généraux": "Gaux", "crédit": "Créd.", "cimetières": "Cim.", "antenne": "Ant.", "médical": "Méd.", "collèges": "Coll.", "musicien": "Music.", "apostolique": "Apost.", "postal": "Post.", "territorial": "Territ.", "urbanisme": "Urb.", "préfectorale": "Préf.", "fondateurs": "Fond.", "information": "Info.", "églises": "Égl.", "ophtalmologue": "Ophtalmo", "congrégation": "Congrég.", "charcutier": "Charc.", "étage": "ét.", "consulat": "Consul.", "public": "Publ.", "ferrée": "Ferr.", "matin": "mat.", "société anonyme à responsabilité limitée": "SARL", "monuments": "Mmts", "protection": "Prot.", "universel": "Univ.", "nationale": "Nale", "président": "Pdt", "provinciale": "Prov.", "agriculteurs": "Agric.", "préfectoral": "Préf.", "xxe": "20e", "alpins": "Alp.", "avant": "av.", "infirmerie": "Infirm.", "deux mil": "2000", "rurale": "Rur.", "administratifs": "Admin.", "octobre": "Oct.", "archipel": "Archip.", "communauté": "Commté", "globales": "Glob.", "alpin": "Alp.", "numéros": "Nºˢ", "lieutenant-colonel": "Lieut.-Col.", "jésus-christ": "J.-C.", "agricole": "Agric.", "sa majesté": "S.Maj.", "associative": "Assoc.", "xxi": "21", "présidentielle": "Pdtle", "moyen": "Moy.", "fédéral": "Féd.", "professionnelle": "Profess.", "tertiaire": "Terti.", "ixe": "9e", "hôpital": "Hôp.", "technologies": "Techno.", "iiie": "3e", "développement": "Dévelop.", "monument": "Mmt", "forestière": "Forest.", "numéro": "Nº", "viticulture": "Vitic.", "traversière": "Traver.", "technique": "Tech.", "électriques": "Électr.", "militaires": "Milit.", "pompier": "Pomp.", "américaine": "Amér.", "préfet": "Préf.", "congrégations": "Congrég.", "pâtissier": "Pâtiss.", "mondial": "Mond.", "ophtalmologie": "Ophtalm.", "sainte": "Ste", "africaine": "Afric.", "aviatrice": "Aviat.", "doyens": "Doy.", "société": "Sté", "majeures": "Maj.", "orientale": "Ori.", "ministère": "Min.", "archiduc": "Archid.", "territoire": "Territ.", "techniques": "Tech.", "île-de-france": "IDF", "globale": "Glob.", "xe": "10e", "xie": "11e", "majeure": "Maj.", "commerciaux": "Commerc.", "maire": "Mair.", "spéciaux": "Spéc.", "grande": "Gde", "messieurs": "MM", "colonel": "Col.", "millénaire": "Mill.", "xi": "11", "urbain": "Urb.", "fédérale": "Féd.", "ferré": "Ferr.", "rivière": "Riv.", "républicain": "Républ.", "grandes": "Gdes", "régiment": "Régim.", "hauts": "Hts", "catégorie": "Catég.", "basses": "Bas.", "xii": "12", "agronomiques": "Agro.", "iie": "2e", "protégée": "Prot.", "sapeur-pompier": "Sap.-pomp." }, "directions": { "est-nord-est": "ENE", "nord-est": "NE", "ouest": "O", "sud-est": "SE", "est-sud-est": "ESE", "nord-nord-est": "NNE", "sud": "S", "nord-nord-ouest": "NNO", "nord-ouest": "NO", "nord": "N", "ouest-sud-ouest": "OSO", "ouest-nord-ouest": "ONO", "sud-ouest": "SO", "