Skip to content

Issue 1 launguage order backend queries #5889

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

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
Original file line number Diff line number Diff line change
Expand Up @@ -702,10 +702,9 @@ public void updateCategories() {
*/
private void buildDepictionList(List<IdAndCaptions> idAndCaptions) {
binding.mediaDetailDepictionContainer.removeAllViews();
String locale = Locale.getDefault().getLanguage();
for (IdAndCaptions idAndCaption : idAndCaptions) {
binding.mediaDetailDepictionContainer.addView(buildDepictLabel(
getDepictionCaption(idAndCaption, locale),
getDepictionCaption(idAndCaption, Locale.getDefault().getLanguage()),
idAndCaption.getId(),
binding.mediaDetailDepictionContainer
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,51 +400,109 @@ public List<Place> getNearbyPlaces(
/**
* Retrieves a list of places based on the provided list of places and language.
*
* @param placeList A list of Place objects for which to fetch information.
* @param language The language code to use for the query.
* @param placeList A list of Place objects for which to fetch information.
* @param language The language code to use for the query.
* @param secondaryLanguages The serialized secondary language code(s) to use for fallback queries.
* @return A list of Place objects with additional information retrieved from Wikidata, or null
* if an error occurs.
* if an error occurs.
* @throws IOException If there is an issue with reading the resource file or executing the HTTP
* request.
*/
@Nullable
public List<Place> getPlaces(
final List<Place> placeList, final String language) throws IOException {
final List<Place> placeList, final String language, final String secondaryLanguages) throws IOException {

// Read the SparQL query template from the resource file
final String wikidataQuery = FileUtils.readFromResource("/queries/query_for_item.rq");

// Split the secondary languages string into an array to use in fallback queries
final String[] secondaryLanguagesArray = secondaryLanguages.split(",\\s*");

// Prepare the Wikidata entity IDs (QIDs) for each place in the list
String qids = "";
for (final Place place : placeList) {
qids += "\n" + ("wd:" + place.getWikiDataEntityId());
}

// Build fallback descriptions for secondary languages in case the primary language is unavailable
StringBuilder fallBackDescription = new StringBuilder();
for (int i = 0; i < secondaryLanguagesArray.length; i++) {
fallBackDescription.append("OPTIONAL {?item schema:description ?itemDescriptionPreferredLanguage_")
.append(i + 1) // Unique identifier for each fallback
.append(". FILTER (lang(?itemDescriptionPreferredLanguage_")
.append(i + 1)
.append(") = \"")
.append(secondaryLanguagesArray[i]) // Use the secondary language code
.append("\")}\n");
}

// Build fallback labels for secondary languages
StringBuilder fallbackLabel = new StringBuilder();
for (int i = 0; i < secondaryLanguagesArray.length; i++) {
fallbackLabel.append("OPTIONAL {?item rdfs:label ?itemLabelPreferredLanguage_")
.append(i + 1)
.append(". FILTER (lang(?itemLabelPreferredLanguage_")
.append(i + 1)
.append(") = \"")
.append(secondaryLanguagesArray[i])
.append("\")}\n");
}

// Build fallback class labels for secondary languages
StringBuilder fallbackClassLabel = new StringBuilder();
for (int i = 0; i < secondaryLanguagesArray.length; i++) {
fallbackClassLabel.append("OPTIONAL {?class rdfs:label ?classLabelPreferredLanguage_")
.append(i + 1)
.append(". FILTER (lang(?classLabelPreferredLanguage_")
.append(i + 1)
.append(") = \"")
.append(secondaryLanguagesArray[i])
.append("\")}\n");
}

// Replace placeholders in the query with actual data: QIDs, language codes, and fallback options
final String query = wikidataQuery
.replace("${ENTITY}", qids)
.replace("${LANG}", language);
.replace("${LANG}", language)
.replace("${SECONDARYDESCRIPTION}", fallBackDescription.toString())
.replace("${SECONDARYLABEL}", fallbackLabel.toString())
.replace("${SECONDARYCLASSLABEL}", fallbackClassLabel.toString());

// Build the URL for the SparQL query with the formatted query string
final HttpUrl.Builder urlBuilder = HttpUrl
.parse(sparqlQueryUrl)
.newBuilder()
.addQueryParameter("query", query)
.addQueryParameter("format", "json");
.addQueryParameter("format", "json"); // Ensure JSON response

// Create and send the HTTP request
final Request request = new Request.Builder()
.url(urlBuilder.build())
.build();

// Execute the request and handle the response
try (Response response = okHttpClient.newCall(request).execute()) {
if (response.isSuccessful()) {
// Parse the JSON response and convert it to a list of NearbyResultItems
final String json = response.body().string();
final NearbyResponse nearbyResponse = gson.fromJson(json, NearbyResponse.class);
final List<NearbyResultItem> bindings = nearbyResponse.getResults().getBindings();

// Convert each NearbyResultItem into a Place object and return the list of places
final List<Place> places = new ArrayList<>();
for (final NearbyResultItem item : bindings) {
final Place placeFromNearbyItem = Place.from(item);
places.add(placeFromNearbyItem);
}
return places;
return places; // Return the list of places with additional information
} else {
// Handle unsuccessful HTTP response codes
throw new IOException("Unexpected response code: " + response.code());
}
}
}


/**
* Make API Call to get Places
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import fr.free.nrw.commons.BaseMarker;
import fr.free.nrw.commons.MapController;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.settings.Prefs;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -16,6 +18,7 @@
import java.util.Locale;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import timber.log.Timber;

public class NearbyController extends MapController {
Expand All @@ -34,6 +37,9 @@ public NearbyController(NearbyPlaces nearbyPlaces) {
this.nearbyPlaces = nearbyPlaces;
}

@Inject
@Named("default_preferences")
JsonKvStore defaultKvStore;

/**
* Prepares Place list to make their distance information update later.
Expand All @@ -56,6 +62,7 @@ public NearbyPlacesInfo loadAttractionsFromLocation(final LatLng currentLatLng,
Timber.d("Loading attractions nearby, but currentLatLng is null");
return null;
}

List<Place> places = nearbyPlaces
.radiusExpander(searchLatLng, Locale.getDefault().getLanguage(), returnClosestResult,
customQuery);
Expand Down Expand Up @@ -139,7 +146,10 @@ public String getPlacesAsGPX(LatLng currentLocation) throws Exception {
* @throws Exception If an error occurs during the retrieval process.
*/
public List<Place> getPlaces(List<Place> placeList) throws Exception {
return nearbyPlaces.getPlaces(placeList, Locale.getDefault().getLanguage());

String secondaryLanguages = defaultKvStore.getString(Prefs.SECONDARY_LANGUAGES, "");

return nearbyPlaces.getPlaces(placeList, Locale.getDefault().getLanguage(), secondaryLanguages);
}

public static LatLng calculateNorthEast(double latitude, double longitude, double distance) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,14 @@ public List<Place> getFromWikidataQuery(
*
* @param placeList A list of Place objects for which to fetch information.
* @param lang The language code to use for the query.
* @param lang2 The serialised secondary language code to use for the query.
* @return A list of Place objects obtained from the Wikidata query.
* @throws Exception If an error occurs during the retrieval process.
*/
public List<Place> getPlaces(final List<Place> placeList,
final String lang) throws Exception {
final String lang, final String lang2) throws Exception {
return okHttpJsonApiClient
.getPlaces(placeList, lang);
.getPlaces(placeList, lang, lang2);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package fr.free.nrw.commons.recentlanguages

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import fr.free.nrw.commons.R
import fr.free.nrw.commons.databinding.RowItemLanguagesSpinnerBinding
import fr.free.nrw.commons.utils.LangCodeUtils
import org.apache.commons.lang3.StringUtils
import java.util.HashMap

/**
* Array adapter for saved languages
*/
class SavedLanguagesAdapter constructor(
context: Context,
var savedLanguages: List<Language>, // List of saved languages
private val selectedLanguages: HashMap<*, String>, // Selected languages map
) : ArrayAdapter<String?>(context, R.layout.row_item_languages_spinner) {
/**
* Selected language code in SavedLanguagesAdapter
* Used for marking selected ones
*/
var selectedLangCode = ""

override fun isEnabled(position: Int) =
savedLanguages[position].languageCode.let {
it.isNotEmpty() && !selectedLanguages.containsValue(it) && it != selectedLangCode
}

override fun getCount() = savedLanguages.size

override fun getView(
position: Int,
convertView: View?,
parent: ViewGroup,
): View {
val binding: RowItemLanguagesSpinnerBinding
var rowView = convertView

if (rowView == null) {
val layoutInflater =
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
binding = RowItemLanguagesSpinnerBinding.inflate(layoutInflater, parent, false)
rowView = binding.root
} else {
binding = RowItemLanguagesSpinnerBinding.bind(rowView)
}

val languageCode = savedLanguages[position].languageCode
val languageName = savedLanguages[position].languageName
binding.tvLanguage.let {
it.isEnabled = isEnabled(position)
if (languageCode.isEmpty()) {
it.text = StringUtils.capitalize(languageName)
it.textAlignment = View.TEXT_ALIGNMENT_CENTER
} else {
it.text =
"${StringUtils.capitalize(languageName)}" +
" [${LangCodeUtils.fixLanguageCode(languageCode)}]"
}
}
return rowView
}

/**
* Provides code of a language from saved languages for a specific position
*/
fun getLanguageCode(position: Int): String = savedLanguages[position].languageCode

/**
* Provides name of a language from saved languages for a specific position
*/
fun getLanguageName(position: Int): String = savedLanguages[position].languageName
}
2 changes: 2 additions & 0 deletions app/src/main/java/fr/free/nrw/commons/settings/Prefs.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public class Prefs {
public static final String UPLOADS_SHOWING = "uploadsshowing";
public static final String MANAGED_EXIF_TAGS = "managed_exif_tags";
public static final String DESCRIPTION_LANGUAGE = "languageDescription";
public static final String SECONDARY_LANGUAGES = "secondaryLanguages";

public static final String APP_UI_LANGUAGE = "appUiLanguage";
public static final String KEY_THEME_VALUE = "appThemePref";

Expand Down
Loading