Skip to content

Commit

Permalink
Merge pull request #3387 from ProjectSidewalk/3377-translate-city-names
Browse files Browse the repository at this point in the history
City names are now translated
  • Loading branch information
misaugstad authored Sep 21, 2023
2 parents 92d991d + 977ca40 commit 934bbb4
Show file tree
Hide file tree
Showing 21 changed files with 308 additions and 218 deletions.
23 changes: 10 additions & 13 deletions app/controllers/ApplicationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import models.audit.AuditTaskInteractionTable
import models.daos.slick.DBTableDefinitions.UserTable
import models.label.TagTable.selectTagsByLabelType
import models.street.StreetEdgePriorityTable
import models.utils.Configs
import models.utils.{CityInfo, Configs}
import models.attribute.ConfigTable
import play.api.Play
import play.api.Play.current
import play.api.i18n.Messages
import play.api.i18n.{Lang, Messages}
import java.util.Calendar
import play.api.mvc._
import scala.concurrent.Future
Expand Down Expand Up @@ -129,17 +129,15 @@ class ApplicationController @Inject() (implicit val env: Environment[User, Sessi
WebpageActivityTable.save(WebpageActivity(0, user.userId.toString, ipAddress, "Visit_Index", timestamp))
// Get city configs.
val cityStr: String = Play.configuration.getString("city-id").get
val cityName: String = Play.configuration.getString("city-params.city-name." + cityStr).get
val stateAbbreviation: String = Play.configuration.getString("city-params.state-abbreviation." + cityStr).get
val cityShortName: String = Play.configuration.getString("city-params.city-short-name." + cityStr).get
val mapathonLink: Option[String] = ConfigTable.getMapathonEventLink
// Get names and URLs for other cities so we can link to them on landing page.
val otherCityUrls: List[(String, String, String, String)] = Configs.getAllCityInfo(excludeCity = cityStr)
val lang: Lang = request.cookies.get("PLAY_LANG").map(l => Lang(l.value)).getOrElse(request.acceptLanguages.head)
val cityUrls: List[CityInfo] = Configs.getAllCityInfo(lang)
// Get total audited distance. If using metric system, convert from miles to kilometers.
val auditedDistance: Float =
if (Messages("measurement.system") == "metric") StreetEdgePriorityTable.auditedStreetDistanceUsingPriority * 1.60934.toFloat
else StreetEdgePriorityTable.auditedStreetDistanceUsingPriority
Future.successful(Ok(views.html.index("Project Sidewalk", Some(user), cityName, stateAbbreviation, cityShortName, mapathonLink, cityStr, otherCityUrls, auditedDistance)))
Future.successful(Ok(views.html.index("Project Sidewalk", Some(user), mapathonLink, cityUrls, auditedDistance)))
}
case None =>
if(qString.isEmpty){
Expand Down Expand Up @@ -374,10 +372,9 @@ class ApplicationController @Inject() (implicit val env: Environment[User, Sessi
val timestamp: Timestamp = new Timestamp(Instant.now.toEpochMilli)
val ipAddress: String = request.remoteAddress

// Get current city.
val cityStr: String = Play.configuration.getString("city-id").get
// Get names and URLs for cities to display in Gallery dropdown.
val cityUrls: List[(String, String, String, String)] = Configs.getAllCityInfo()
val lang: Lang = request.cookies.get("PLAY_LANG").map(l => Lang(l.value)).getOrElse(request.acceptLanguages.head)
val cityInfo: List[CityInfo] = Configs.getAllCityInfo(lang)
val labelTypes: List[(String, String)] = List(
("Assorted", Messages("gallery.all")),
("CurbRamp", Messages("curb.ramp")),
Expand All @@ -403,7 +400,7 @@ class ApplicationController @Inject() (implicit val env: Environment[User, Sessi
val activityStr: String = s"Visit_Gallery_LabelType=${labType}_Severity=${severityList}_Tags=${tagList}_Validations=$valOptions"
WebpageActivityTable.save(WebpageActivity(0, user.userId.toString, ipAddress, activityStr, timestamp))

Future.successful(Ok(views.html.gallery("Gallery", Some(user), cityStr, cityUrls, labType, labelTypes, severityList, tagList, valOptions)))
Future.successful(Ok(views.html.gallery("Gallery", Some(user), cityInfo, labType, labelTypes, severityList, tagList, valOptions)))
case None =>
// Send them through anon signup so that there activities on sidewalk gallery are logged as anon.
// UTF-8 codes needed to pass a URL that contains parameters: ? is %3F, & is %26
Expand Down Expand Up @@ -474,8 +471,8 @@ class ApplicationController @Inject() (implicit val env: Environment[User, Sessi

WebpageActivityTable.save(WebpageActivity(0, user.userId.toString, ipAddress, "Visit_Map", timestamp))
val cityStr: String = Play.configuration.getString("city-id").get
val cityShortName: String = Play.configuration.getString("city-params.city-short-name." + cityStr).get
Future.successful(Ok(views.html.accessScoreDemo("Project Sidewalk - Explore Accessibility", Some(user), cityShortName)))
val cityNameShort: Option[String] = Play.configuration.getString(s"city-params.city-short-name.$cityStr")
Future.successful(Ok(views.html.accessScoreDemo("Project Sidewalk - Explore Accessibility", Some(user), cityStr, cityNameShort)))
case None =>
Future.successful(Redirect("/anonSignUp?url=/demo"))
}
Expand Down
26 changes: 13 additions & 13 deletions app/controllers/AuditController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ class AuditController @Inject() (implicit val env: Environment[User, SessionAuth
// mission, but only after every third explore mission after that.
val completedMissions: Boolean = MissionTable.countCompletedMissions(user.userId, missionType = "audit") > 0

val cityStr: String = Play.configuration.getString("city-id").get
val cityId: String = Play.configuration.getString("city-id").get
val tutorialStreetId: Int = ConfigTable.getTutorialStreetId
val cityShortName: String = Play.configuration.getString("city-params.city-short-name." + cityStr).get
val cityNameShort: Option[String] = Play.configuration.getString("city-params.city-short-name." + cityId)
if (missionSetProgress.missionType != "audit") {
Future.successful(Redirect("/validate"))
} else {
// On the crowdstudy server, we want to assign users to a study group.
val response = Ok(views.html.explore("Project Sidewalk - Audit", task, mission, region.get, userRoute, missionSetProgress.numComplete, completedMissions, nextTempLabelId, Some(user), cityShortName, tutorialStreetId))
if (cityStr == "crowdstudy" && studyGroup.nonEmpty) Future.successful(response.withCookies(Cookie("SIDEWALK_STUDY_GROUP", studyGroup, httpOnly = false)))
val response = Ok(views.html.explore("Project Sidewalk - Audit", task, mission, region.get, userRoute, missionSetProgress.numComplete, completedMissions, nextTempLabelId, Some(user), cityId, cityNameShort, tutorialStreetId))
if (cityId == "crowdstudy" && studyGroup.nonEmpty) Future.successful(response.withCookies(Cookie("SIDEWALK_STUDY_GROUP", studyGroup, httpOnly = false)))
else Future.successful(response)
}
// For anonymous users.
Expand Down Expand Up @@ -201,13 +201,13 @@ class AuditController @Inject() (implicit val env: Environment[User, SessionAuth
// mission, but only after every third explore mission after that.
val completedMission: Boolean = MissionTable.countCompletedMissions(user.userId, missionType = "audit") > 0

val cityStr: String = Play.configuration.getString("city-id").get
val cityId: String = Play.configuration.getString("city-id").get
val tutorialStreetId: Int = ConfigTable.getTutorialStreetId
val cityShortName: String = Play.configuration.getString("city-params.city-short-name." + cityStr).get
val cityNameShort: Option[String] = Play.configuration.getString("city-params.city-short-name." + cityId)
if (missionSetProgress.missionType != "audit") {
Future.successful(Redirect("/validate"))
} else {
Future.successful(Ok(views.html.explore("Project Sidewalk - Audit", task, mission, region, None, missionSetProgress.numComplete, completedMission, nextTempLabelId, Some(user), cityShortName, tutorialStreetId)))
Future.successful(Ok(views.html.explore("Project Sidewalk - Audit", task, mission, region, None, missionSetProgress.numComplete, completedMission, nextTempLabelId, Some(user), cityId, cityNameShort, tutorialStreetId)))
}
case None =>
Logger.error(s"Tried to explore region $regionId, but there is no neighborhood with that id.")
Expand Down Expand Up @@ -267,25 +267,25 @@ class AuditController @Inject() (implicit val env: Environment[User, SessionAuth
mission = MissionTable.resumeOrCreateNewAuditMission(userId, regionId, payPerMeter, tutorialPay).get
}

val cityStr: String = Play.configuration.getString("city-id").get
val cityId: String = Play.configuration.getString("city-id").get
val tutorialStreetId: Int = ConfigTable.getTutorialStreetId
val cityShortName: String = Play.configuration.getString("city-params.city-short-name." + cityStr).get
val cityNameShort: Option[String] = Play.configuration.getString("city-params.city-short-name." + cityId)

if (missionSetProgress.missionType != "audit") {
Future.successful(Redirect("/validate"))
} else {
// If user is an admin and a panoId or lat/lng are supplied, send to that location, o/w send to street.
if (isAdmin(request.identity) && (startAtPano || startAtLatLng)) {
panoId match {
case Some(panoId) => Future.successful(Ok(views.html.explore("Project Sidewalk - Audit", Some(task), mission, region, None, missionSetProgress.numComplete, completedMission, nextTempLabelId, Some(user), cityShortName, tutorialStreetId, None, None, Some(panoId))))
case Some(panoId) => Future.successful(Ok(views.html.explore("Project Sidewalk - Audit", Some(task), mission, region, None, missionSetProgress.numComplete, completedMission, nextTempLabelId, Some(user), cityId, cityNameShort, tutorialStreetId, None, None, Some(panoId))))
case None =>
(lat, lng) match {
case (Some(lat), Some(lng)) => Future.successful(Ok(views.html.explore("Project Sidewalk - Audit", Some(task), mission, region, None, missionSetProgress.numComplete, completedMission, nextTempLabelId, Some(user), cityShortName, tutorialStreetId, Some(lat), Some(lng))))
case (_, _) => Future.successful(Ok(views.html.explore("Project Sidewalk - Audit", Some(task), mission, region, None, missionSetProgress.numComplete, completedMission, nextTempLabelId, None, cityShortName, tutorialStreetId)))
case (Some(lat), Some(lng)) => Future.successful(Ok(views.html.explore("Project Sidewalk - Audit", Some(task), mission, region, None, missionSetProgress.numComplete, completedMission, nextTempLabelId, Some(user), cityId, cityNameShort, tutorialStreetId, Some(lat), Some(lng))))
case (_, _) => Future.successful(Ok(views.html.explore("Project Sidewalk - Audit", Some(task), mission, region, None, missionSetProgress.numComplete, completedMission, nextTempLabelId, None, cityId, cityNameShort, tutorialStreetId)))
}
}
} else {
Future.successful(Ok(views.html.explore("Project Sidewalk - Audit", Some(task), mission, region, None, missionSetProgress.numComplete, completedMission, nextTempLabelId, Some(user), cityShortName, tutorialStreetId)))
Future.successful(Ok(views.html.explore("Project Sidewalk - Audit", Some(task), mission, region, None, missionSetProgress.numComplete, completedMission, nextTempLabelId, Some(user), cityId, cityNameShort, tutorialStreetId)))
}
}
}
Expand Down
9 changes: 0 additions & 9 deletions app/controllers/ConfigController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,6 @@ class ConfigController @Inject() (implicit val env: Environment[User, SessionAut
)))
}

/**
* Get the short version of the current city name.
*/
def getCityShortNameParam() = Action.async { implicit request =>
val cityStr: String = Play.configuration.getString("city-id").get
val cityShortName: String = Play.configuration.getString("city-params.city-short-name." + cityStr).get
Future.successful(Ok(Json.obj("city_short_name" -> cityShortName)))
}

/**
* Get all city-specific parameters needed for the API page demos.
*/
Expand Down
33 changes: 23 additions & 10 deletions app/models/utils/Configs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,35 @@ package models.utils
import play.api.Play
import play.api.Play.current
import scala.collection.JavaConverters._
import play.api.i18n.{Lang, Messages}

case class CityInfo(cityId: String, countryId: String, cityNameShort: String, cityNameFormatted: String, URL: String, visibility: String)

object Configs {
/**
* Returns list of all cities -- (cityId, name + ", " + state, cityURL, visibility) -- excluding the city specified.
* Returns list of info for all cities, including formatted names (in current language), URL, visibility.
*/
def getAllCityInfo(excludeCity: String = ""): List[(String, String, String, String)] = {
def getAllCityInfo(lang: Lang): List[CityInfo] = {
val currentCityId: String = Play.configuration.getString("city-id").get
val currentCountryId: String = Play.configuration.getString(s"city-params.country-id.$currentCityId").get
val envType: String = Play.configuration.getString("environment-type").get

// Get names and URLs for cities to display in Gallery dropdown.
val cities: List[String] =
Play.configuration.getStringList("city-params.city-ids").get.asScala.toList.filterNot(_ == excludeCity)
val cityInfo: List[(String, String, String, String)] = cities.map { cityId =>
val name: String = Play.configuration.getString("city-params.city-name." + cityId).get
val state: String = Play.configuration.getString("city-params.state-abbreviation." + cityId).get
val cityURL: String = Play.configuration.getString("city-params.landing-page-url." + envType + "." + cityId).get
val visibility: String = Play.configuration.getString("city-params.status." + cityId).get
(cityId, name + ", " + state, cityURL, visibility)
val cityIds: List[String] = Play.configuration.getStringList("city-params.city-ids").get.asScala.toList
val cityInfo: List[CityInfo] = cityIds.map { cityId =>
val stateId: Option[String] = Play.configuration.getString(s"city-params.state-id.$cityId")
val countryId: String = Play.configuration.getString(s"city-params.country-id.$cityId").get
val cityURL: String = Play.configuration.getString(s"city-params.landing-page-url.$envType.$cityId").get
val visibility: String = Play.configuration.getString(s"city-params.status.$cityId").get

// Get the name of the city in frequently used formats in the current language.
val cityName: String = Messages(s"city.name.$cityId")(lang)
val cityNameShort: String = Play.configuration.getString(s"city-params.city-short-name.$cityId").getOrElse(cityName)
val cityNameFormatted: String = if (currentCountryId == "usa" && stateId.isDefined && countryId == "usa")
Messages("city.state", cityName, Messages(s"state.name.${stateId.get}")(lang))(lang)
else
Messages("city.state", cityName, Messages(s"country.name.$countryId")(lang))(lang)
CityInfo(cityId, countryId, cityNameShort, cityNameFormatted, cityURL, visibility)
}
cityInfo
}
Expand Down
4 changes: 2 additions & 2 deletions app/views/accessScoreDemo.scala.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@import models.user.User
@(title: String, user: Option[User] = None, cityShortName: String)(implicit lang: Lang)
@(title: String, user: Option[User] = None, cityId: String, cityNameShort: Option[String])(implicit lang: Lang)

@main(title) {
@navbar(user, Some("/demo"))
Expand All @@ -16,7 +16,7 @@
<div id="map-text" class="map-text-box">
<h2>Access Score<sub><span style="font-size: 15"><b>beta</b></span></sub> in Action</h2>
<p>
Find out about neighborhood accessibility of @cityShortName! Here, accessible neighborhoods are colored in <span class="bold" style="color: #4dac26;">green</span>
Find out about neighborhood accessibility of @{cityNameShort.getOrElse(Messages(s"city.name.$cityId"))}! Here, accessible neighborhoods are colored in <span class="bold" style="color: #4dac26;">green</span>
and inaccessible neighborhoods are colored in <span style="color: #d01c8b;" class="bold">red</span>.
</p>
<p>
Expand Down
10 changes: 5 additions & 5 deletions app/views/explore.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
@import models.amt.AMTAssignmentTable
@import models.route.UserRoute
@import views.html.bootstrap._
@import play.api.Play
@import play.api.Play.current

@(title: String, task: Option[models.audit.NewTask] = None, mission: Mission, region: Region, userRoute: Option[UserRoute], missionSetProgress: Int, hasCompletedMission: Boolean, nextTempLabelId: Int, user: Option[User] = None, cityShortName: String, tutorialStreetId: Int, lat: Option[Double] = None, lng: Option[Double] = None, panoId: Option[String] = None)(implicit lang: Lang)
@(title: String, task: Option[models.audit.NewTask] = None, mission: Mission, region: Region, userRoute: Option[UserRoute], missionSetProgress: Int, hasCompletedMission: Boolean, nextTempLabelId: Int, user: Option[User] = None, cityId: String, cityNameShort: Option[String], tutorialStreetId: Int, lat: Option[Double] = None, lng: Option[Double] = None, panoId: Option[String] = None)(implicit lang: Lang)
@cityName = @{cityNameShort.getOrElse(Messages(s"city.name.$cityId"))}

@main(title, Some("/explore")) {
@navbar(user, Some("/explore"))
Expand Down Expand Up @@ -366,7 +365,7 @@ <h1 class="status-holder-header-1">@Messages("audit.right.ui.overall.stats")</h1
</div>
<div id="neighborhood-stats-status-box" class="status-box">
<h1 class="status-holder-header-1">@Messages("audit.right.ui.current.neighborhood")</h1>
<span id="status-neighborhood-name"><span id="status-holder-neighborhood-name"></span>@cityShortName</span>
<span id="status-neighborhood-name"><span id="status-holder-neighborhood-name"></span>@cityName</span>
<div class="status-row" id="neighborhood-status-row">
<img src='@routes.Assets.at("images/icons/noun_distance_2587675_cropped.png")' class="status-icon" alt="@Messages("distance.icon.alt")" align="">
<span><strong id="status-audited-distance">0.00</strong> <small>@Messages("audit.right.ui.distance")</small></span>
Expand Down Expand Up @@ -1027,7 +1026,8 @@ <h3 id="modal-mission-complete-progress-title"></h3>
}

mainParam.language = "@lang.code";
mainParam.cityId = "@Play.configuration.getString("city-id").get"
mainParam.cityId = "@cityId";
mainParam.cityName = "@cityName";

svl.main = new Main(mainParam);
}
Expand Down
Loading

0 comments on commit 934bbb4

Please sign in to comment.