translate via i18next

This commit is contained in:
Gautier Pelloux-Prayer 2019-02-24 10:21:54 +01:00
parent a8c9bf0c6d
commit f54d72644b
20 changed files with 1410 additions and 155 deletions

View file

@ -45,65 +45,67 @@ BR.Map = {
maxNativeZoom: 19,
maxZoom: maxZoom,
subdomains: ['server', 'services'],
attribution: '<a target="_blank" href="http://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9">Esri World Imagery</a>'
attribution: '<a target="_blank" href="http://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9">' + i18next.t('credits.esri-tiles') + '</a>'
});
var cycling = L.tileLayer('https://tile.waymarkedtrails.org/cycling/{z}/{x}/{y}.png', {
maxNativeZoom: 18,
opacity: 0.7,
maxZoom: maxZoom,
attribution: '<a target="_blank" href="http://cycling.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}">Cycling</a>'
attribution: '<a target="_blank" href="http://cycling.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}">' + i18next.t('map.cycling') + '</a>'
});
var hiking = L.tileLayer('https://tile.waymarkedtrails.org/hiking/{z}/{x}/{y}.png', {
maxNativeZoom: 18,
opacity: 0.7,
maxZoom: maxZoom,
attribution: '<a target="_blank" href="http://hiking.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}">Hiking</a>'
attribution: '<a target="_blank" href="http://hiking.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}">' + i18next.t('map.hiking') + '</a>'
});
map = new L.Map('map', {
zoomControl: false, // add it manually so that we can translate it
worldCopyJump: true
});
L.control.zoom({
zoomInTitle: i18next.t('map.zoomInTitle'),
zoomOutTitle: i18next.t('map.zoomOutTitle'),
}).addTo(map);
if (!map.restoreView()) {
map.setView([50.99, 9.86], 6);
}
// two attribution lines by adding two controls, prevents ugly wrapping on
// small screens, better separates static from layer-specific attribution
var osmAttribution = $(map.getContainer()).outerWidth() >= 400 ? i18next.t('map.attribution-osm-long') : i18next.t('map.attribution-osm-short');
map.attributionControl.setPrefix(
'&copy; <a target="_blank" href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>' +
($(map.getContainer()).outerWidth() >= 400 ? ' contributers' : '') +
' &middot; <a href="" data-toggle="modal" data-target="#credits">Copyright</a>' +
' &middot; <a target="_blank" href="http://brouter.de/privacypolicy.html">Privacy</a>');
'&copy; <a target="_blank" href="https://www.openstreetmap.org/copyright">' + osmAttribution + '</a>' +
' &middot; <a href="" data-toggle="modal" data-target="#credits">' + i18next.t('map.copyright') + '</a>' +
' &middot; <a target="_blank" href="http://brouter.de/privacypolicy.html">' + i18next.t('map.privacy') + '</a>');
new L.Control.PermalinkAttribution().addTo(map);
map.attributionControl.setPrefix(false);
var baseLayers = {
'OpenStreetMap': osm,
'OpenStreetMap.de': osmde,
'OpenTopoMap': topo,
'OpenCycleMap (Thunderf.)': cycle,
'Outdoors (Thunderforest)': outdoors,
'Esri World Imagery': esri
};
var overlays = {
'Cycling (Waymarked Trails)': cycling,
'Hiking (Waymarked Trails)': hiking
};
var baseLayers = {}
baseLayers[i18next.t('map.layer.osm')] = osm;
baseLayers[i18next.t('map.layer.osmde')] = osmde;
baseLayers[i18next.t('map.layer.topo')] = topo;
baseLayers[i18next.t('map.layer.cycle')] = cycle;
baseLayers[i18next.t('map.layer.outdoors')] = outdoors;
baseLayers[i18next.t('map.layer.esri')] = esri;
var overlays = {}
overlays[i18next.t('map.layer.cycling')] = cycling;
overlays[i18next.t('map.layer.hiking')] = hiking;
if (BR.keys.bing) {
baseLayers['Bing Aerial'] = new BR.BingLayer(BR.keys.bing);
baseLayers[i18next.t('map.layer.bing')] = new BR.BingLayer(BR.keys.bing);
}
if (BR.keys.digitalGlobe) {
var recent = new L.tileLayer('https://{s}.tiles.mapbox.com/v4/digitalglobe.nal0g75k/{z}/{x}/{y}.png?access_token=' + BR.keys.digitalGlobe, {
minZoom: 1,
maxZoom: 19,
attribution: '&copy; <a href="https://www.digitalglobe.com/platforms/mapsapi">DigitalGlobe</a> ('
+ '<a href="https://bit.ly/mapsapiview">Terms of Use</a>)'
attribution: i18next.t('credits.digitalglobe-license')
});
baseLayers['DigitalGlobe Recent Imagery'] = recent;
baseLayers[i18next.t('map.layer.digitalglobe')] = recent;
}
if (BR.conf.clearBaseLayers) {
@ -131,6 +133,9 @@ BR.Map = {
var secureContext = 'isSecureContext' in window ? isSecureContext : location.protocol === 'https:';
if (secureContext) {
L.control.locate({
strings: {
title: i18next.t('map.locate-me')
},
icon: 'fa fa-location-arrow',
iconLoading: 'fa fa-spinner fa-pulse',
}).addTo(map);

View file

@ -22,7 +22,7 @@ BR.Util = {
},
getError: function(xhr) {
var msg = 'no response from server';
var msg = i18next.t('warning.no-response');
if (xhr.responseText) {
msg = xhr.responseText;
} else if (xhr.status || xhr.statusText) {

View file

@ -25,10 +25,13 @@ BR.Layers = L.Class.extend({
info: false,
searching: false,
paging: false,
language: {
emptyTable: i18next.t("sidebar.layers.table.empty")
},
columns: [
{ title: "Name" },
{ title: "URL" },
{ title: "Type" }
{ title: i18next.t("sidebar.layers.table.name") },
{ title: i18next.t("sidebar.layers.table.URL") },
{ title: i18next.t("sidebar.layers.table.type") }
]
});
},

View file

@ -37,7 +37,7 @@ BR.Message = L.Class.extend({
showError: function (err) {
if (err == 'Error: target island detected for section 0\n') {
err = 'Error: cannot find a route for given points. Maybe try to move them closer to roads?';
err = i18next.t('warning.no-route-found');
}
this._show(err, 'error');
},

View file

@ -28,7 +28,7 @@ BR.OpacitySlider = L.Control.extend({
};
$(container).html(input);
$(container).attr('title', 'Set transparency of route track and markers');
$(container).attr('title', i18next.t('map.opacity-slider'));
input.slider({
min: 0,

View file

@ -9,7 +9,7 @@ BR.RoutingOptions = L.Evented.extend({
for (var i = 0; i < profiles.length; i++) {
var option = document.createElement("option");
option.value = profiles[i];
option.text = profiles[i];
option.text = i18next.t("navbar.profile." + profiles[i]);
profiles_list.appendChild(option);
}
// set default value, used as indicator for empty custom profile

View file

@ -59,7 +59,7 @@
routing.draw(false);
control.state('activate-draw');
},
title: 'Stop drawing route (ESC key)'
title: i18next.t('map.draw-route-stop')
}, {
stateName: 'activate-draw',
icon: 'fa-pencil',
@ -67,7 +67,7 @@
routing.draw(true);
control.state('deactivate-draw');
},
title: 'Draw route (D key)'
title: i18next.t('map.draw-route-start')
}]
});
@ -76,11 +76,11 @@
function () {
bootbox.prompt({
size: 'small',
title: "Delete route?",
title: i18next.t('map.delete-route'),
inputType: 'checkbox',
inputOptions: [
{
text: '&nbsp;&nbsp;also delete all no-go areas',
text: i18next.t('map.delete-nogo-areas'),
value: 'nogo'
}
],
@ -96,7 +96,7 @@
}
});
},
'Clear route'
i18next.t('map.clear-route')
);
function updateRoute(evt) {
@ -122,6 +122,11 @@
profile.update(evt.options);
});
BR.NogoAreas.MSG_BUTTON = i18next.t("map.nogo.draw");
BR.NogoAreas.MSG_BUTTON_CANCEL = i18next.t("map.nogo.cancel");
BR.NogoAreas.MSG_CREATE = i18next.t("map.nogo.click-drag");
BR.NogoAreas.MSG_DISABLED = i18next.t("map.nogo.edit");
BR.NogoAreas.MSG_ENABLED = i18next.t("map.nogo.help");
nogos = new BR.NogoAreas();
nogos.on('update', updateRoute);
@ -145,8 +150,7 @@
options: routingOptions.getOptions()
});
if (!saveWarningShown) {
profile.message.showWarning('<strong>Note:</strong> Uploaded custom profiles are only cached temporarily on the server.'
+ '<br/>Please save your edits to your local PC.');
profile.message.showWarning(i18next.t('warning.temporary-profile'));
saveWarningShown = true;
}
} else {
@ -241,12 +245,14 @@
nogos.preventRoutePointOnCreate(routing);
if (BR.keys.strava) {
const stravaControl = new L.Control.StravaSegments(
{
const stravaControl = L.control.stravaSegments({
runningTitle: i18next.t('map.strava-running'),
bikingTitle: i18next.t('map.strava-biking'),
loadingTitle: i18next.t('map.loading'),
stravaToken: BR.keys.strava
})
.addTo(map);
layersControl.addOverlay(stravaControl.stravaLayer, "Strava segments");
layersControl.addOverlay(stravaControl.stravaLayer, i18next.t('map.layer.strava-segments'));
}
map.addControl(new BR.OpacitySlider({
@ -352,8 +358,20 @@
});
}
mapContext = BR.Map.initMap();
verifyTouchStyle(mapContext);
initApp(mapContext);
i18next
.use(window.i18nextXHRBackend)
.use(window.i18nextBrowserLanguageDetector)
.init({
fallbackLng: 'en',
backend: {
loadPath: 'locales/{{lng}}.json',
}
}, function(err, t) {
jqueryI18next.init(i18next, $);
$('html').localize();
mapContext = BR.Map.initMap();
verifyTouchStyle(mapContext);
initApp(mapContext);
});
})();

View file

@ -4,7 +4,7 @@ BR.NogoAreas = L.Control.extend({
MSG_BUTTON_CANCEL: 'Cancel drawing no-go area',
MSG_CREATE: 'Click and drag to draw circle',
MSG_DISABLED: 'Click to edit',
MSG_ENABLED: '&square; = move / resize, <span class="fa fa-trash-o"></span> = delete,<br>click nogo to quit editing',
MSG_ENABLED: '&square; = move / resize, <span class="fa fa-trash-o"></span> = delete,<br>click circle to quit editing',
STATE_CREATE: 'no-go-create',
STATE_CANCEL: 'cancel-no-go-create'
},
@ -116,9 +116,7 @@ BR.NogoAreas = L.Control.extend({
return {
nogos: this.drawnItems.getLayers().filter(function (e) { return e instanceof L.Circle; }),
polygons: this.drawnItems.getLayers().filter(function (e) { return e instanceof L.Polygon; }),
polylines: this.drawnItems.getLayers().filter(function (e) {
return (e instanceof L.Polyline) && !(e instanceof L.Polygon);
}),
polylines: this.drawnItems.getLayers().filter(function (e) { return e instanceof L.Polyline; }),
};
},
@ -228,10 +226,7 @@ BR.EditingTooltip = L.Handler.extend({
// works better with zooming than updating offset to match radius
layer.openTooltip = function (layer, latlng) {
if (!latlng && layer instanceof L.Layer) {
latlng = L.latLng(
layer.getBounds().getSouth(),
0.5 * (layer.getBounds().getWest() + layer.getBounds().getEast())
);
latlng = L.latLng(layer.getBounds().getSouth(), layer.getLatLng().lng);
}
L.Layer.prototype.openTooltip.call(this, layer, latlng);
};

View file

@ -125,7 +125,7 @@ L.BRouter = L.Class.extend({
xhr = new XMLHttpRequest();
if (!url) {
return cb(new Error('Error getting route URL'));
return cb(new Error(i18next.t('warning.cannot-get-route')));
}
xhr.open('GET', url, true);
@ -179,7 +179,7 @@ L.BRouter = L.Class.extend({
xhr.onload = L.bind(this._handleProfileResponse, this, xhr, cb);
xhr.onerror = function(evt) {
var xhr = this;
cb('Upload error: ' + xhr.statusText);
cb(i18next.t('warning.upload-error', {error: xhr.statusText}));
};
// send profile text only, as text/plain;charset=UTF-8
@ -193,7 +193,7 @@ L.BRouter = L.Class.extend({
response = JSON.parse(xhr.responseText);
cb(response.error, response.profileid);
} else {
cb('Profile error: no or empty response from server');
cb(i18next.t('warning.profile-error'));
}
},