Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding translations #144

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 33 additions & 28 deletions DataStructures/TurnInstructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
#define TURNINSTRUCTIONS_H_

#include <string>
#include <iostream>
#include <fstream>
using namespace std;

//This is a hack until c++0x is available enough to use scoped enums
struct TurnInstructionsClass {
Expand All @@ -45,35 +48,37 @@ struct TurnInstructionsClass {
std::string TurnStrings[15];
std::string Ordinals[11];

//This is a hack until c++0x is available enough to use initializer lists.
TurnInstructionsClass(){
TurnStrings [0] = "";
TurnStrings [1] = "Continue";
TurnStrings [2] = "Turn slight right";
TurnStrings [3] = "Turn right";
TurnStrings [4] = "Turn sharp right";
TurnStrings [5] = "U-Turn";
TurnStrings [6] = "Turn sharp left";
TurnStrings [7] = "Turn left";
TurnStrings [8] = "Turn slight left";
TurnStrings [9] = "Reach via point";
TurnStrings[10] = "Head";
TurnStrings[11] = "Enter round-about";
TurnStrings[12] = "Leave round-about";
TurnStrings[13] = "Stay on round-about";
TurnStrings[14] = "Start";
TurnInstructionsClass(){
};

Ordinals[0] = "zeroth";
Ordinals[1] = "first";
Ordinals[2] = "second";
Ordinals[3] = "third";
Ordinals[4] = "fourth";
Ordinals[5] = "fifth";
Ordinals[6] = "sixth";
Ordinals[7] = "seventh";
Ordinals[8] = "eighth";
Ordinals[9] = "nineth";
Ordinals[10] = "tenth";
//This is a hack until c++0x is available enough to use initializer lists.
TurnInstructionsClass(string nameFile){
// Declare an input file stream
ifstream fread;
// Open a file for only read
fread.open(nameFile.c_str(), ifstream::in);
// Check if there have been any error
if (!fread){
cout << "Fault to read: " << nameFile.c_str() << endl;
}
// Create a buffer to use for read
char buffer[128];
// Read from file to buffer
fread.getline(buffer, 128);
int i = 0;
while (!fread.eof()){
/* Write the result in an array */
std::string str(buffer);
if(i<15){
TurnStrings[i] = str;
}else if(i>=15 && i<26){
Ordinals[i-15] = str;
}
/* Read the next line */
i++;
fread.getline(buffer, 128);
}
fread.close();
};

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the Util/BaseConfiguration.h to load this information. Format the language files as simple ini files. This gives a lot more structure to the internationalization and does not introduce any new loading code.

static inline double GetTurnDirectionOfInstruction( const double angle ) {
Expand Down
139 changes: 139 additions & 0 deletions DataStructures/TurnInstructionsList.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#ifndef TURNINSTRUCTIONSLIST_H_
#define TURNINSTRUCTIONSLIST_H_

#include <list>
#include <iostream>
#include <vector>
#include <string>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <cctype>
#include <boost/algorithm/string.hpp>
#include "./TurnInstructions.h"

struct TurnInstructionsListClass {

// Class to go over directory hierachy
list<TurnInstructionsClass> tilist;
vector<string> languages;

TurnInstructionsListClass(){};

TurnInstructionsListClass(std::string path){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always pass strings as reference. The extra allocation is expensive.

vector<string> archivos;
vector<string>::iterator posArchivo;
posArchivo = archivos.begin();
FindFile(path.c_str(), archivos);
TurnInstructionsClass ti;
// Vector with the file names to read
for (int i = 0; i < archivos.size(); ++i){
ti = TurnInstructionsClass(archivos.at(i));
posArchivo++;
tilist.push_back(ti);
}
};

void FindFile (const char dirname[], vector<string> &archivos){
static DIR *dir;
static struct dirent *mi_dirent;
// Check if the directory have opened correctly
if((dir = opendir(dirname)) == NULL)
cout << "Fault in opendir" << endl;;
// Go over directory content
while ((mi_dirent = readdir(dir)) != NULL){
// If it's not (.) or (..)
if (strcmp (mi_dirent->d_name, ".") != 0 && strcmp (mi_dirent->d_name, "..") != 0){
struct stat structura;
// Read the complete path
string dirnameString = dirname;
string nameFile = mi_dirent->d_name;
string pathFile = dirnameString + "/" + nameFile;
if (stat(pathFile.c_str(), &structura) < 0){
cout << "Fault in stat" << endl;
}else if (structura.st_mode & S_IFREG){
archivos.reserve(archivos.size() + 2);
archivos.push_back(pathFile);
boost::to_upper(nameFile);
languages.reserve(languages.size() + 2);
languages.push_back(nameFile);
}else if(structura.st_mode & S_IFDIR){
FindFile(mi_dirent->d_name, archivos);
}
}
}
if(closedir(dir) == -1){
cout << "Fault in closedir" << endl;
}
}

TurnInstructionsClass getTurnInstructions(std::string language){
boost::to_upper(language);
list <TurnInstructionsClass>::iterator pos;
int index = -1;
// In case the language is empty
if(index == -1 && language == ""){
for(int i=0; i<languages.size(); i++){
if(languages.at(i).find("EN")==0){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has linear runtime and is considered bad. A hash map is much more usable here.

index = i;
break;
}
}
}
// In case the request language is the same name than we have in the directory hierachy
for(int i=0; i<languages.size(); i++){
if(language.compare(languages.at(i)) == 0){
index = i;
break;
}
}
// In case the request language is the same language but the name is not exactly the same
// Example: Request parameter: 'lang=ES' and file name is 'ES_ES'
if(index == -1){
for(int i=0; i<languages.size(); i++){
if(language != "" && languages.at(i).find(language)==0){
index = i;
break;
}
}
}
// In case the request language is the same language but the name is not exactly the same
// Example: Request parameter: 'lang=ES_ES' and file name is 'ES'
if(index == -1){
for(int i=0; i<languages.size(); i++){
if(language.find(languages.at(i))==0){
index = i;
break;
}
}
}
// In case the request language was an included language in another language
// Example: Request parameter: 'lang=ES_AR' and file name is 'ES'
if(index == -1){
for(int i=0; i<languages.size(); i++){
int pos = language.find("_");
string lang = language.substr(0, pos);
if(languages.at(i).find(lang)==0){
index = i;
break;
}
}
}
// In case the request parameter language doesn't exist, the default language is 'EN'
if(index == -1){
for(int i=0; i<languages.size(); i++){
if(languages.at(i).find("EN")==0){
index = i;
break;
}
}
}
pos = tilist.begin();
for(int i=0; i<index; i++){
pos++;
}
return *pos;
}
};

#endif /* TURNINSTRUCTIONSLIST_H_ */
26 changes: 26 additions & 0 deletions DataStructures/languages/EN_EN
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

Continue
Turn slight right
Turn right
Turn sharp right
U-Turn
Turn sharp left
Turn left
Turn slight left
Reach via point
Head
Enter round-about
Leave round-about
Stay on round-about
Start
zeroth
first
second
third
fourth
fifth
sixth
seventh
eighth
nineth
tenth
26 changes: 26 additions & 0 deletions DataStructures/languages/ES_ES
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

Continuar
Gire a la derecha
Gire a la derecha
Gire a la derecha aguda
U-Turn
Girar a la izquierda
Gire a la izquierda
Gire a la izquierda
Llegar a un punto intermedio
Cabeza
Introduzca rotonda
Deja rotonda
Permanezca en rotonda
Comenzar
cero
primero
segundo
tercero
cuarto
quinto
sexto
séptimo
octavo
noveno
décimo
26 changes: 26 additions & 0 deletions DataStructures/languages/fr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

Continuer
Tourner à droite
Tourner à droite
Tournez à droite forte
U-Turn
Tourner à gauche
Tourner à gauche
Tourner à gauche
Parvenir à un compromis
Tête
Entrez rond-point
Laissez rond-point
Rester sur rond-point
Commencer
zéro
première
deuxième
troisième
quatrième
cinquième
sixième
septième
huitième
neuvième
dixième
4 changes: 3 additions & 1 deletion Descriptors/BaseDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ or see http://www.gnu.org/licenses/agpl.txt.

#include "../typedefs.h"
#include "../DataStructures/ExtractorStructs.h"
#include "../DataStructures/TurnInstructions.h"
#include "../DataStructures/HashTable.h"
#include "../Util/StringUtil.h"

Expand All @@ -48,7 +49,8 @@ class BaseDescriptor {
BaseDescriptor() { }
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() { }
virtual void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) = 0;
// Add translations
virtual void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance, TurnInstructionsClass ti) = 0;
virtual void SetConfig(const _DescriptorConfig & config) = 0;
};

Expand Down
3 changes: 2 additions & 1 deletion Descriptors/GPXDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ or see http://www.gnu.org/licenses/agpl.txt.

#include <boost/foreach.hpp>
#include "BaseDescriptor.h"
#include "../DataStructures/TurnInstructions.h"

template<class SearchEngineT>
class GPXDescriptor : public BaseDescriptor<SearchEngineT>{
Expand All @@ -33,7 +34,7 @@ class GPXDescriptor : public BaseDescriptor<SearchEngineT>{
std::string tmp;
public:
void SetConfig(const _DescriptorConfig& c) { config = c; }
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) {
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance, TurnInstructionsClass ti) {
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content += "<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
Expand Down
16 changes: 8 additions & 8 deletions Descriptors/JSONDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
JSONDescriptor() {}
void SetConfig(const _DescriptorConfig & c) { config = c; }

void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, const unsigned durationOfTrip) {
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, const unsigned durationOfTrip, TurnInstructionsClass ti) {
WriteHeaderToOutput(reply.content);
if(durationOfTrip != INT_MAX) {
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
Expand Down Expand Up @@ -102,23 +102,23 @@ class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
std::string tmpDist, tmpLength, tmpDuration, tmpBearing;
//Fetch data from Factory and generate a string from it.
BOOST_FOREACH(SegmentInformation & segment, descriptionFactory.pathDescription) {
if(TurnInstructions.TurnIsNecessary( segment.turnInstruction) ) {
if(TurnInstructions.EnterRoundAbout == segment.turnInstruction) {
if(ti.TurnIsNecessary( segment.turnInstruction) ) {
if(ti.EnterRoundAbout == segment.turnInstruction) {
roundAbout.nameID = segment.nameID;
roundAbout.startIndex = prefixSumOfNecessarySegments;
} else {
if(0 != prefixSumOfNecessarySegments)
reply.content += ",";

reply.content += "[\"";
if(TurnInstructions.LeaveRoundAbout == segment.turnInstruction) {
reply.content += TurnInstructions.TurnStrings[TurnInstructions.EnterRoundAbout];
if(ti.LeaveRoundAbout == segment.turnInstruction) {
reply.content += ti.TurnStrings[ti.EnterRoundAbout];
reply.content += " and leave at ";
reply.content += TurnInstructions.Ordinals[roundAbout.leaveAtExit+1];
reply.content += ti.Ordinals[roundAbout.leaveAtExit+1];
reply.content += " exit";
roundAbout.leaveAtExit = 0;
} else {
reply.content += TurnInstructions.TurnStrings[segment.turnInstruction];
reply.content += ti.TurnStrings[segment.turnInstruction];
}
reply.content += "\",\"";
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
Expand All @@ -141,7 +141,7 @@ class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
reply.content += tmpBearing;
reply.content += "]";
}
} else if(TurnInstructions.StayOnRoundAbout == segment.turnInstruction) {
} else if(ti.StayOnRoundAbout == segment.turnInstruction) {
++roundAbout.leaveAtExit;
}
if(segment.necessary)
Expand Down
Loading