Commit d5921229 authored by Adrien Pavie's avatar Adrien Pavie
Browse files

Translation system done

parent 5b5abbde
......@@ -60,7 +60,8 @@ var Main = function(divId, mode, config) {
],
"locales": [
"locales/en.yaml"
"locales/en.yaml",
"locales/fr.yaml"
],
"api": {
......
......@@ -140,7 +140,7 @@ var Level = L.Control.extend({
//If too many levels
if(btnOverflow) {
$(this.container).addClass("level-control-container-full");
var btnUp = this._createButton("", "See higher levels", 'level-control-scroll-up', this.container, this._scroll.bind(this, "up"));
var btnUp = this._createButton("", this.options.t("map.level.up.desc"), 'level-control-scroll-up', this.container, this._scroll.bind(this, "up"));
if(!util.isMobileBrowser()) {
L.DomEvent.on(btnUp, 'mouseover', this._scroll.bind(this, "up", "start"));
L.DomEvent.on(btnUp, 'mouseout', this._scroll.bind(this, "up", "stop"));
......@@ -155,7 +155,7 @@ var Level = L.Control.extend({
this._createLevels(levelsContainer);
var btnDown = this._createButton("", "See lower levels", 'level-control-scroll-down', this.container, this._scroll.bind(this, "down"));
var btnDown = this._createButton("", this.options.t("map.level.down.desc"), 'level-control-scroll-down', this.container, this._scroll.bind(this, "down"));
if(!util.isMobileBrowser()) {
L.DomEvent.on(btnDown, 'mouseover', this._scroll.bind(this, "down", "start"));
L.DomEvent.on(btnDown, 'mouseout', this._scroll.bind(this, "down", "stop"));
......
......@@ -131,18 +131,18 @@ var Main = function(divId, mode, config, rulesets, newNoteService, searchService
}
}.bind(this));
this.map.attributionControl.setPrefix('<img src="img/favicon.png" /> <a href="http://openlevelup.net">'+t("main.olu")+'</a>');
this.layersManager = new MapLayersManager(this.map);
this.map.attributionControl.setPrefix('<img src="img/favicon.png" /> <a href="http://openlevelup.net">'+t("olu.name")+'</a>');
this.layersManager = new MapLayersManager(this.map, t);
var hash = new L.Hash(this.map);
/***************************************************************************
* Create controls
*/
this.side = Side("olu-map-side", { autoPan: false });
this.side = Side("olu-map-side", { autoPan: false, t: t });
this.messages = Messages("olu-messages");
this.spinner = Spinner("olu-spinner");
this.level = Level({ position: "topright" });
this.level = Level({ position: "topright", t: t });
var levelControl = this.level; //To have access in editor control
var zoomControl = L.control.zoom({ position: "topright" });
var scaleControl = L.control.scale({ position: "bottomleft" });
......@@ -264,7 +264,7 @@ var Main = function(divId, mode, config, rulesets, newNoteService, searchService
this.side.contents.newnote.set(
newNoteService,
function() {
this.messages.show("The note was successfully sent", "info");
this.messages.show(t("notes.sent"), "info");
this.side.hide();
//TODO Reload notes data if already shown
......@@ -380,7 +380,7 @@ var Main = function(divId, mode, config, rulesets, newNoteService, searchService
if(zoom >= this.config.map.dataMinZoom) {
//Download new data
if(this.bounds.features == undefined || !this.bounds.features.contains(bounds)) {
this.spinner.show("Retrieving building data", "download");
this.spinner.show(t("data.download.building"), "download");
this.bounds.features = bounds.pad(1.1 + 0.5 * (zoom - this.config.map.dataMinZoom));
//Retrieve pictures
......@@ -391,7 +391,7 @@ var Main = function(divId, mode, config, rulesets, newNoteService, searchService
this.pictures.flickr = photos;
}.bind(this),
function() {
this.messages.show("Flickr pictures can't be retrieved", "error");
this.messages.show(t("data.pictures.fail", { provider: "Flickr" }), "error");
}.bind(this)
);
......@@ -446,7 +446,7 @@ var Main = function(divId, mode, config, rulesets, newNoteService, searchService
this.spinner.hide();
}.bind(this),
function(e) {
this.messages.show(e.message || "Can't retrieve data", "error");
this.messages.show(e.message || t("data.download.fail"), "error");
this.spinner.hide();
}.bind(this)
);
......@@ -498,7 +498,7 @@ var Main = function(divId, mode, config, rulesets, newNoteService, searchService
if(zoom >= this.config.map.clusterMinZoom && zoom < this.config.map.dataMinZoom) {
//Download new data
if(this.bounds.cluster == undefined || !this.bounds.cluster.contains(bounds)) {
this.spinner.show("Retrieving location data", "download");
this.spinner.show(t("data.download.location"), "download");
this.bounds.cluster = bounds.pad(1.1);
console.log("[Main] Start download cluster data");
osmProvider.downloadCluster(
......@@ -508,7 +508,7 @@ var Main = function(divId, mode, config, rulesets, newNoteService, searchService
this.spinner.hide();
}.bind(this),
function(e) {
this.messages.show(e.message || "Can't retrieve data", "error");
this.messages.show(e.message || t("data.download.fail"), "error");
this.spinner.hide();
}.bind(this)
);
......@@ -525,7 +525,7 @@ var Main = function(divId, mode, config, rulesets, newNoteService, searchService
if(zoom < this.config.map.clusterMinZoom) {
clearPreviousDataLayer();
//TODO Better handling of those messages
this.messages.show("Zoom in to see data", "info", 1000);
this.messages.show(t("map.zoom.showdata"), "info", 1000);
}
}.bind(this);
......
......@@ -26,7 +26,7 @@ var util = require("../utils");
* Manager for map layers, reading external data and creating appropriate map layers.
* Adding/removing layers from map is not handled here.
*/
var MapLayersManager = function(map) {
var MapLayersManager = function(map, t) {
//ATTRIBUTES
/** The leaflet map **/
this.map = map;
......@@ -34,6 +34,9 @@ var MapLayersManager = function(map) {
/** The layers **/
this.layers = { notes: null, cluster: null, features: null, tiles: null };
/** The translator **/
this.t = t;
/** The markers **/
this.markers = {
noteOpen: L.icon({
......@@ -73,11 +76,11 @@ MapLayersManager.prototype.setNotes = function(notes) {
L.marker(
n.coordinates,
{
title: "Note #"+n.id,
title: this.t("notes.id", { id: n.id }),
icon: (n.status == "closed") ? this.markers.noteClosed : this.markers.noteOpen
}
).bindPopup(
"<h3>Note #"+n.id+"</h3>"+
"<h3>"+this.t("notes.id", { id: n.id })+"</h3>"+
"<p>Status: "+n.status+"<br /><a href=\"\">Details</a></p>"
)
);
......
......@@ -32,23 +32,25 @@ var SideContentLayers = require('./sidecontent/Layers');
*/
var Side = L.Control.Sidebar.extend({
//ATTRIBUTES
contents: {
search: new SideContentSearch(),
routing: new SideContentRouting(),
notes: new SideContentNotes(),
newnote: new SideContentNewNote(),
parameters: new SideContentParameters(),
help: new SideContentHelp(),
feature: new SideContentFeature(),
layers: new SideContentLayers()
},
halfsize: [ "search", "routing", "notes", "newnote", "feature" ],
//OTHER METHODS
initialize: function(placeholder, options) {
L.Control.Sidebar.prototype.initialize.call(this, placeholder, options);
if(options.t) { this.t = options.t; }
this.contents = {
search: new SideContentSearch(this.t),
routing: new SideContentRouting(),
notes: new SideContentNotes(this.t),
newnote: new SideContentNewNote(this.t),
parameters: new SideContentParameters(),
help: new SideContentHelp(),
feature: new SideContentFeature(this.t),
layers: new SideContentLayers(this.t)
};
//Create each side content
for(var c in this.contents) {
L.DomUtil.create("div", "side-content side-content-"+c, this.getContainer())
......
......@@ -21,7 +21,7 @@ var Mapillary = require("mapillary-js");
/**
* Feature content for side bar
*/
var Feature = function() {
var Feature = function(t) {
//ATTRIBUTES
/** The current feature **/
this._feature = null;
......@@ -40,6 +40,9 @@ var Feature = function() {
/** The mapillary viewer **/
this._mapillaryViewer = null;
/** The translation function **/
this.t = t;
};
//ACCESSORS
......@@ -52,7 +55,7 @@ Feature.prototype.get = function() {
if(this._feature != null) {
var title = $(
"<div class=\"side-content-feature-title\"><h2>"+((this._feature.name) ? this._feature.name : ((this._feature.category) ? this._feature.category : this._feature.id))+"</h2>"+
((this._feature.category != this._feature.name && this._feature.category != null) ? "<span>"+this._feature.category+"</span>" : "<span>Feature</span>")+
((this._feature.category != this._feature.name && this._feature.category != null) ? "<span>"+this._feature.category+"</span>" : "<span>"+this.t("feature.name")+"</span>")+
"</div>"
);
element.append(title);
......@@ -81,7 +84,7 @@ Feature.prototype.get = function() {
if(this._feature.getImages().count() > 0) {
var images = this._feature.getImages().get();
for(var i=0; i < images.length; i++) {
pictures.append($("<div class=\"side-content-feature-picture basic\"><img src=\""+images[i].img+"\" alt=\"Loading image...\" /></div>").hide());
pictures.append($("<div class=\"side-content-feature-picture basic\"><img src=\""+images[i].img+"\" alt=\""+this.t("pictures.loading")+"\" /></div>").hide());
}
}
......@@ -94,7 +97,7 @@ Feature.prototype.get = function() {
}
//Stub image
else {
pictures.append("<div class=\"side-content-feature-picture basic\"><img src=\"img/stub_feature.jpg\" alt=\"Loading image...\" /></div>");
pictures.append("<div class=\"side-content-feature-picture basic\"><img src=\"img/stub_feature.jpg\" alt=\""+this.t("pictures.loading")+"\" /></div>");
}
element.append(pictures);
......@@ -128,7 +131,7 @@ Feature.prototype.get = function() {
*/
if(this._options.showTags) {
var tags = $("<div class=\"side-content-feature-tags\"></div>");
tags.append("<h3>Tags</h3>");
tags.append("<h3>"+this.t("features.tags")+"</h3>");
var table = $("<table></table>");
......@@ -253,7 +256,7 @@ Feature.prototype._detail = function(osmKey, d) {
result += "<a href=\""+val+"\">"+val+"</a>";
}
else {
result += "Invalid URL";
result += this.t("features.url.invalid");
}
break;
......@@ -262,12 +265,12 @@ Feature.prototype._detail = function(osmKey, d) {
result += "<a href=\"mailto:"+val+"\">"+val+"</a>";
}
else {
result += "Invalid email address";
result += this.t("features.email.invalid");
}
break;
case "hours":
result += "<a href=\"http://projets.pavie.info/yohours/?oh="+encodeURIComponent(val)+"\" target=\"_blank\">Click to see hours</a>";
result += "<a href=\"http://projets.pavie.info/yohours/?oh="+encodeURIComponent(val)+"\" target=\"_blank\">"+this.t("features.hours.show")+"</a>";
break;
case "text_bind":
......
......@@ -20,7 +20,7 @@ var $ = require('jquery');
/**
* Layers content for side bar
*/
var Layers = function() {
var Layers = function(t) {
//ATTRIBUTES
/** The map **/
this._map = null;
......@@ -42,6 +42,9 @@ var Layers = function() {
/** The map coordinates **/
this._coords = { lat: 48.12114, lng: -1.71129, zoom: 18 };
/** The translator function **/
this.t = t;
};
//ACCESSORS
......@@ -53,7 +56,7 @@ Layers.prototype.get = function() {
var element = $("<div/>");
if(this._styles) {
element.append("<h2>Style</h2>");
element.append("<h2>"+this.t("map.layers.name")+"</h2>");
var styles = $("<div id=\"side-content-layers-styles\"></div>");
//Read each meta style
......@@ -91,7 +94,7 @@ Layers.prototype.get = function() {
}
if(this._bases) {
element.append("<h2>Background</h2>");
element.append("<h2>"+this.t("map.layers.background")+"</h2>");
var bases = $("<div id=\"side-content-layers-bases\"></div>");
this._basesId = [];
......
......@@ -20,7 +20,7 @@ var $ = require('jquery');
/**
* New note content for side bar
*/
var NewNote = function() {
var NewNote = function(t) {
//ATTRIBUTES
/** The new note service **/
this._newNote = null;
......@@ -36,6 +36,9 @@ var NewNote = function() {
/** The fail handler **/
this._fail = null;
/** The translator function **/
this.t = t;
};
//ACCESSORS
......@@ -45,22 +48,22 @@ var NewNote = function() {
NewNote.prototype.get = function() {
var element = $("<div/>");
element.append("<h2>Add a note</h2>");
element.append("<p>Spotted a mistake or something missing? Let other people know so we can fix it. Move the marker to the correct position and type a note to explain the problem.<br />(Please don't enter personal information or information from copyrighted maps or directory listings)</p>");
element.append("<textarea id=\"sidecontent-newnote-textarea\">"+((this._level !== null) ? "Level "+this._level+": " : "")+"</textarea>");
element.append("<h2>"+this.t("notes.add.name")+"</h2>");
element.append("<p>"+this.t("notes.add.desc")+"<br />"+this.t("notes.add.privacy")+"</p>");
element.append("<textarea id=\"sidecontent-newnote-textarea\">"+((this._level !== null) ? this.t("map.level.value", { l: this._level })+": " : "")+"</textarea>");
var buttons = $("<div class=\"sidecontent-newnote-buttons\"></div>");
//Send button
var sendBtnDiv = $("<div class=\"sidecontent-newnote-button\">");
var sendBtn = $("<button id=\"sidecontent-newnote-send\" class=\"success\" type=\"button\">Add</button>");
var sendBtn = $("<button id=\"sidecontent-newnote-send\" class=\"success\" type=\"button\">"+this.t("buttons.add")+"</button>");
sendBtn.click(this._sendNote.bind(this));
sendBtnDiv.append(sendBtn);
buttons.append(sendBtnDiv);
//Cancel button
var cancelBtnDiv = $("<div class=\"sidecontent-newnote-button\">");
var cancelBtn = $("<button id=\"sidecontent-newnote-cancel\" class=\"warning\" type=\"button\">Cancel</button>");
var cancelBtn = $("<button id=\"sidecontent-newnote-cancel\" class=\"warning\" type=\"button\">"+this.t("buttons.cancel")+"</button>");
cancelBtnDiv.append(cancelBtn);
buttons.append(cancelBtnDiv);
......@@ -87,8 +90,8 @@ NewNote.prototype.set = function(service, success, fail) {
*/
NewNote.prototype.setLevel = function(l) {
var text = $("#sidecontent-newnote-textarea");
if(text.val() == undefined || text.val().trim().length == 0 || text.val().trim() == "Level "+this._level+":") {
text.val("Level "+l+": ");
if(text.val() == undefined || text.val().trim().length == 0 || text.val().trim() == this.t("map.level.value", { l: this._level })+":") {
text.val(this.t("map.level.value", { l: l })+": ");
}
this._level = l;
......@@ -112,7 +115,7 @@ NewNote.prototype._sendNote = function() {
this._coords == null
|| textVal == undefined
|| textVal.trim().length == 0
|| textVal.trim() == "Level "+this._level+":"
|| textVal.trim() == this.t("map.level.value", { l: this._level })+":"
) {
this._fail(new Error("view.sidecontent.NewNote.invalidParameters"));
}
......
......@@ -20,9 +20,12 @@ var $ = require('jquery');
/**
* Notes content for side bar
*/
var Notes = function() {
var Notes = function(t) {
//ATTRIBUTES
this.note = null;
/** The translator function **/
this.t = t;
};
//ACCESSORS
......@@ -33,22 +36,22 @@ Notes.prototype.get = function() {
var element = $("<div/>");
if(this.note != null) {
element.append("<h2>Note #"+this.note.id+"</h2>");
element.append("<h2>"+this.t("notes.id", { id: +this.note.id })+"</h2>");
var list = $("<ul class=\"note-comments\"></ul>");
var comment;
for(var i=0; i < this.note.comments.length; i++) {
comment = this.note.comments[i];
commentDetails = comment.action;
commentDetails += (comment.user) ? " by <a href=\"http://www.openstreetmap.org/user/"+comment.user+"\">"+comment.user+"</a>" : " by an anonym user";
commentDetails += " on "+comment.date;
commentDetails = (comment.user) ?
this.t("notes.comment.user", { user: comment.user, action: this.t("notes.action."+comment.action), date: comment.date })
: this.t("notes.comment.anon", { action: comment.action, date: comment.date });
list.append("<li><span class=\"comment\">"+comment.text+"</span><span class=\"comment-details\">"+commentDetails+"</span>");
}
element.append(list);
element.append("<p class=\"note-footer\"><a href=\"http://www.openstreetmap.org/note/"+this.note.id+"\">See on OpenStreetMap</a></p>");
element.append("<p class=\"note-footer\"><a href=\"http://www.openstreetmap.org/note/"+this.note.id+"\">"+this.t("data.view.osm")+"</a></p>");
}
return element;
......
......@@ -20,13 +20,16 @@ var $ = require('jquery');
/**
* Search content for side bar
*/
var Search = function() {
var Search = function(t) {
//ATTRIBUTES
/** The search service **/
this._service = null;
/** The map instance **/
this._map = null;
/** The translator function **/
this.t = t;
};
//ACCESSORS
......@@ -35,10 +38,10 @@ var Search = function() {
*/
Search.prototype.get = function() {
var element = $("<div/>");
element.append("<h2>Search</h2>");
element.append("<h2>"+this.t("search.name")+"</h2>");
var searchArea = $("<div class=\"sidecontent-search-area input-field\"></div>");
var searchText = $("<input type=\"text\" id=\"sidecontent-search-field\" placeholder=\"Where do you want to go ?\" />");
var searchText = $("<input type=\"text\" id=\"sidecontent-search-field\" placeholder=\""+this.t("search.ask")+"\" />");
searchText.keypress(function(e) {
if(e.which == 13) {
this._search();
......@@ -47,7 +50,7 @@ Search.prototype.get = function() {
}.bind(this));
var searchButtonContainer = $("<span class=\"btn\"></span>");
var searchButton = $("<button id=\"sidecontent-search-valid\" class=\"success\" type=\"button\">Search</button>");
var searchButton = $("<button id=\"sidecontent-search-valid\" class=\"success\" type=\"button\">"+this.t("buttons.search")+"</button>");
searchButton.click(this._search.bind(this));
searchArea.append(searchText);
......@@ -115,7 +118,7 @@ Search.prototype._show = function(result) {
$("#sidecontent-search-results").append(list);
}
else {
$("#sidecontent-search-results").text("No result found");
$("#sidecontent-search-results").text(this.t("search.results.none"));
}
};
......@@ -124,7 +127,7 @@ Search.prototype._show = function(result) {
*/
Search.prototype._error = function(e) {
$("#sidecontent-search-results").empty();
$("#sidecontent-search-results").text("An error occured");
$("#sidecontent-search-results").text(this.t("search.error"));
console.error(e);
};
......
......@@ -4,13 +4,70 @@ en:
notes:
desc: Propose a map correction
sent: The note was successfully sent
id: "Note #{id}"
add:
name: Add a note
desc: Spotted a mistake or something missing? Let other people know so we can fix it. Move the marker to the correct position and type a note to explain the problem.
privacy: "(Please don't enter personal information or information from copyrighted maps or directory listings)"
actions:
opened: opened
closed: closed
reopened: reopened
commented: commented
comment:
user: "{action} by <a href='http://www.openstreetmap.org/user/{user}'>{user}</a> on {date}"
anon: "{action} by an anonym user on {date}"
buttons:
add: Add
cancel: Cancel
search: Search
search:
desc: Find a place in the world
name: Search
ask: Where do you want to go ?
results:
none: No result found
error: An error occured
map:
layers:
name: Style
desc: Change map background and style
background: Background
zoom:
showdata: Zoom in to see data
level:
up:
desc: See higher levels
down:
desc: See lower levels
value: "Level {l}"
routing:
desc: Find direction between two places
data:
download:
building: Retrieving building data
location: Retrieving location data
fail: Can't retrieve data
pictures:
fail: "{provider} pictures can't be retrieved"
view:
osm: See on OpenStreetMap
pictures:
loading: Loading image...
features:
name: Feature
tags: Tags
url:
invalid: Invalid URL
email:
invalid: Invalid email address
hours:
show: Click to see hours
fr:
olu:
name: OpenLevelUp!
notes:
desc: Suggérer une amélioration de la carte
sent: La note a été ajoutée avec succès
id: "Note n°{id}"
add:
name: Ajouter une note
desc: Vous avez constaté un manque ou une erreur ? Faites-le savoir aux contributeurs pour que la carte soit améliorée. Déplacez le marqueur à la position exacte et décrivez le problème.
privacy: "(N'entrez pas d'informations personnelles ou provenant de sources non libres de droits)"
actions:
opened: ouvert
closed: fermé
reopened: réouvert
commented: commenté
comment:
user: "{action} par <a href='http://www.openstreetmap.org/user/{user}'>{user}</a> le {date}"
anon: "{action} par un utilisateur anonyme le {date}"
buttons:
add: Ajouter
cancel: Annuler
search: Rechercher
search:
desc: Trouver un lieu sur Terre
name: Recherche
ask: Où souhaitez-vous aller ?
results:
none: Aucun résultat trouvé
error: Une erreur s'est produite
map:
layers:
name: Style
desc: Changer le fond et le style de carte
background: Fond de carte
zoom:
showdata: Zoomez pour voir les données
level:
up:
desc: Voir le niveau supérieur
down:
desc: Voir le niveau inférieur
value: "Niveau {l}"
routing:
desc: Trouver l'itinéraire entre deux lieux
data:
download:
building: Téléchargement des bâtiments
location: Téléchargement de la zone