mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 21:03:54 +01:00
Draft for MR 1
This commit is contained in:
parent
4c9637c821
commit
1fbbc072d4
10 changed files with 326 additions and 10 deletions
|
|
@ -388,19 +388,65 @@ class OkHttpJsonApiClient @Inject constructor(
|
|||
|
||||
@Throws(IOException::class)
|
||||
fun getPlaces(
|
||||
placeList: List<Place>, language: String
|
||||
placeList: List<Place>, primaryLanguage: String, secondaryLanguages: String
|
||||
): List<Place>? {
|
||||
val wikidataQuery = FileUtils.readFromResource("/queries/query_for_item.rq")
|
||||
|
||||
// Split the secondary languages string into an array to use in fallback queries
|
||||
val secondaryLanguagesArray = secondaryLanguages.split(",\\s*".toRegex())
|
||||
|
||||
// Prepare the Wikidata entity IDs (QIDs) for each place in the list
|
||||
var qids = ""
|
||||
for (place in placeList) {
|
||||
qids += """
|
||||
${"wd:" + place.wikiDataEntityId}"""
|
||||
qids += "\nwd:${place.wikiDataEntityId}"
|
||||
}
|
||||
|
||||
// Build fallback descriptions for secondary languages in case the primary language is unavailable
|
||||
val fallBackDescription = StringBuilder()
|
||||
secondaryLanguagesArray.forEachIndexed { index, lang ->
|
||||
fallBackDescription.append("OPTIONAL {?item schema:description ?itemDescriptionPreferredLanguage_")
|
||||
.append(index + 1)
|
||||
.append(". FILTER (lang(?itemDescriptionPreferredLanguage_")
|
||||
.append(index + 1)
|
||||
.append(") = \"")
|
||||
.append(lang)
|
||||
.append("\")}\n")
|
||||
}
|
||||
|
||||
// Build fallback labels for secondary languages
|
||||
val fallbackLabel = StringBuilder()
|
||||
secondaryLanguagesArray.forEachIndexed { index, lang ->
|
||||
fallbackLabel.append("OPTIONAL {?item rdfs:label ?itemLabelPreferredLanguage_")
|
||||
.append(index + 1)
|
||||
.append(". FILTER (lang(?itemLabelPreferredLanguage_")
|
||||
.append(index + 1)
|
||||
.append(") = \"")
|
||||
.append(lang)
|
||||
.append("\")}\n")
|
||||
}
|
||||
|
||||
// Build fallback class labels for secondary languages
|
||||
val fallbackClassLabel = StringBuilder()
|
||||
secondaryLanguagesArray.forEachIndexed { index, lang ->
|
||||
fallbackClassLabel.append("OPTIONAL {?class rdfs:label ?classLabelPreferredLanguage_")
|
||||
.append(index + 1)
|
||||
.append(". FILTER (lang(?classLabelPreferredLanguage_")
|
||||
.append(index + 1)
|
||||
.append(") = \"")
|
||||
.append(lang)
|
||||
.append("\")}\n")
|
||||
}
|
||||
|
||||
// Replace placeholders in the query with actual data: QIDs, language codes, and fallback options
|
||||
val query = wikidataQuery
|
||||
.replace("\${ENTITY}", qids)
|
||||
.replace("\${LANG}", language)
|
||||
val urlBuilder: HttpUrl.Builder = sparqlQueryUrl.toHttpUrlOrNull()!!
|
||||
.newBuilder()
|
||||
.replace("\${LANG}", primaryLanguage)
|
||||
.replace("\${SECONDARYDESCRIPTION}", fallBackDescription.toString())
|
||||
.replace("\${SECONDARYLABEL}", fallbackLabel.toString())
|
||||
.replace("\${SECONDARYCLASSLABEL}", fallbackClassLabel.toString())
|
||||
|
||||
// Build the URL for the SparQL query with the formatted query string
|
||||
val urlBuilder = sparqlQueryUrl.toHttpUrlOrNull()!!.newBuilder()
|
||||
.addQueryParameter("query", query)
|
||||
.addQueryParameter("format", "json")
|
||||
|
||||
|
|
@ -418,11 +464,12 @@ ${"wd:" + place.wikiDataEntityId}"""
|
|||
}
|
||||
return places
|
||||
} else {
|
||||
throw IOException("Unexpected response code: " + response.code)
|
||||
throw IOException("Unexpected response code: ${response.code}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun getPlacesAsKML(leftLatLng: LatLng, rightLatLng: LatLng): String? {
|
||||
var kmlString = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ import androidx.annotation.MainThread;
|
|||
import androidx.annotation.Nullable;
|
||||
import fr.free.nrw.commons.BaseMarker;
|
||||
import fr.free.nrw.commons.MapController;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.settings.Prefs;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -16,6 +18,7 @@ import java.util.ListIterator;
|
|||
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 {
|
||||
|
|
@ -34,6 +37,10 @@ public class NearbyController extends MapController {
|
|||
this.nearbyPlaces = nearbyPlaces;
|
||||
}
|
||||
|
||||
@Inject
|
||||
@Named("default_preferences")
|
||||
JsonKvStore defaultKvStore;
|
||||
|
||||
|
||||
/**
|
||||
* Prepares Place list to make their distance information update later.
|
||||
|
|
@ -139,7 +146,8 @@ public class NearbyController extends MapController {
|
|||
* @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) {
|
||||
|
|
|
|||
|
|
@ -131,9 +131,9 @@ public class NearbyPlaces {
|
|||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ object Prefs {
|
|||
const val UPLOADS_SHOWING = "uploadsShowing"
|
||||
const val MANAGED_EXIF_TAGS = "managed_exif_tags"
|
||||
const val DESCRIPTION_LANGUAGE = "languageDescription"
|
||||
const val SECONDARY_LANGUAGES = "secondaryLanguages"
|
||||
const val APP_UI_LANGUAGE = "appUiLanguage"
|
||||
const val KEY_THEME_VALUE = "appThemePref"
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import android.widget.AdapterView
|
|||
import android.widget.EditText
|
||||
import android.widget.ListView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||
|
|
@ -73,6 +74,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
|
||||
private var themeListPreference: ListPreference? = null
|
||||
private var descriptionLanguageListPreference: Preference? = null
|
||||
private var descriptionSecondaryLanguagesListPreference: Preference? = null
|
||||
private var appUiLanguageListPreference: Preference? = null
|
||||
private var showDeletionButtonPreference: Preference? = null
|
||||
private var keyLanguageListPreference: String? = null
|
||||
|
|
@ -204,6 +206,12 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
}
|
||||
|
||||
descriptionSecondaryLanguagesListPreference = findPreference("descriptionSecondaryLanguagesPref")
|
||||
descriptionSecondaryLanguagesListPreference?.setOnPreferenceClickListener {
|
||||
prepareSecondaryLanguagesDialog()
|
||||
true
|
||||
}
|
||||
|
||||
showDeletionButtonPreference = findPreference("displayDeletionButton")
|
||||
showDeletionButtonPreference?.setOnPreferenceChangeListener { _, newValue ->
|
||||
val isEnabled = newValue as Boolean
|
||||
|
|
@ -299,6 +307,82 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun prepareSecondaryLanguagesDialog() {
|
||||
val languageCode = getCurrentLanguageCode("descriptionSecondaryLanguagesPref")
|
||||
val selectedLanguages = hashMapOf<Int, String>()
|
||||
languageCode?.let {
|
||||
selectedLanguages[0] = Locale.getDefault().language
|
||||
}
|
||||
|
||||
val savedLanguages = arrayListOf<Language>()
|
||||
languageCode?.split(",\\s*".toRegex())?.forEach { code ->
|
||||
if (code != Locale.getDefault().language) {
|
||||
val locale = Locale(code)
|
||||
savedLanguages.add(Language(locale.displayLanguage, code))
|
||||
}
|
||||
}
|
||||
|
||||
val dialog = Dialog(requireActivity())
|
||||
dialog.setContentView(R.layout.dialog_select_secondary_languages)
|
||||
dialog.setCanceledOnTouchOutside(true)
|
||||
dialog.window?.setLayout(
|
||||
(resources.displayMetrics.widthPixels * 0.90).toInt(),
|
||||
(resources.displayMetrics.heightPixels * 0.90).toInt()
|
||||
)
|
||||
dialog.show()
|
||||
|
||||
val editText: EditText = dialog.findViewById(R.id.search_language)
|
||||
val listView: ListView = dialog.findViewById(R.id.language_list)
|
||||
val savedLanguageListView: ListView = dialog.findViewById(R.id.language_history_list)
|
||||
val separator: View = dialog.findViewById(R.id.separator)
|
||||
|
||||
updateSavedLanguages(savedLanguageListView, savedLanguages, selectedLanguages)
|
||||
|
||||
val languagesAdapter = LanguagesAdapter(requireActivity(), selectedLanguages)
|
||||
listView.adapter = languagesAdapter
|
||||
|
||||
editText.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(charSequence: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {
|
||||
languagesAdapter.filter.filter(charSequence)
|
||||
}
|
||||
override fun afterTextChanged(editable: Editable?) {}
|
||||
})
|
||||
|
||||
savedLanguageListView.setOnItemClickListener { _, _, position, _ ->
|
||||
savedLanguages.removeAt(position)
|
||||
updateSavedLanguages(savedLanguageListView, savedLanguages, selectedLanguages)
|
||||
saveLanguageValue(
|
||||
savedLanguages.joinToString(", ") { it.languageCode },
|
||||
"descriptionSecondaryLanguagesPref"
|
||||
)
|
||||
}
|
||||
|
||||
listView.setOnItemClickListener { _, _, position, _ ->
|
||||
val selectedLanguageCode = languagesAdapter.getLanguageCode(position)
|
||||
val selectedLanguageName = languagesAdapter.getLanguageName(position)
|
||||
|
||||
if (savedLanguages.any { it.languageCode == selectedLanguageCode }) {
|
||||
Toast.makeText(requireActivity(), "Language already selected", Toast.LENGTH_SHORT).show()
|
||||
return@setOnItemClickListener
|
||||
}
|
||||
|
||||
savedLanguages.add(Language(selectedLanguageName, selectedLanguageCode))
|
||||
updateSavedLanguages(savedLanguageListView, savedLanguages, selectedLanguages)
|
||||
saveLanguageValue(
|
||||
savedLanguages.joinToString(", ") { it.languageCode },
|
||||
"descriptionSecondaryLanguagesPref"
|
||||
)
|
||||
}
|
||||
|
||||
dialog.setOnDismissListener {
|
||||
saveLanguageValue(
|
||||
savedLanguages.joinToString(", ") { it.languageCode },
|
||||
"descriptionSecondaryLanguagesPref"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare and Show language selection dialog box
|
||||
* Uses previously saved language if there is any, if not uses phone locale as initial language.
|
||||
|
|
@ -497,6 +581,16 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
}
|
||||
|
||||
// Helper function to update saved languages
|
||||
private fun updateSavedLanguages(
|
||||
savedLanguageListView: ListView,
|
||||
savedLanguages: List<Language>,
|
||||
selectedLanguages: HashMap<Int, String>
|
||||
) {
|
||||
val savedLanguagesAdapter = RecentLanguagesAdapter(requireActivity(), savedLanguages, selectedLanguages)
|
||||
savedLanguageListView.adapter = savedLanguagesAdapter
|
||||
}
|
||||
|
||||
/**
|
||||
* Save userSelected language in List Preference
|
||||
* @param userSelectedValue
|
||||
|
|
@ -506,6 +600,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
when (preferenceKey) {
|
||||
"appUiDefaultLanguagePref" -> defaultKvStore.putString(Prefs.APP_UI_LANGUAGE, userSelectedValue)
|
||||
"descriptionDefaultLanguagePref" -> defaultKvStore.putString(Prefs.DESCRIPTION_LANGUAGE, userSelectedValue)
|
||||
"descriptionSecondaryLanguagesPref" -> defaultKvStore.putString(Prefs.SECONDARY_LANGUAGES, userSelectedValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -522,6 +617,9 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
"descriptionDefaultLanguagePref" -> defaultKvStore.getString(
|
||||
Prefs.DESCRIPTION_LANGUAGE, ""
|
||||
)
|
||||
"descriptionSecondaryLanguagesPref" -> defaultKvStore.getString(
|
||||
Prefs.SECONDARY_LANGUAGES, ""
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/search_language"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:hint="Type Language Name"
|
||||
android:padding="12dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/language_order_preference"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="Language order preference"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/search_language" />
|
||||
|
||||
<ListView
|
||||
android:id="@+id/language_history_list"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/separator"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/language_order_preference" />
|
||||
|
||||
<View
|
||||
android:id="@+id/separator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/black"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/language_history_list" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/all_languages"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="All Languages"
|
||||
app:layout_constraintTop_toBottomOf="@id/separator"
|
||||
app:layout_constraintEnd_toEndOf="@+id/language_history_list"
|
||||
android:layout_margin="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ListView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:id="@+id/language_list"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/all_languages" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -551,6 +551,7 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="dialog_box_text_nomination">Why should %1$s be deleted?</string>
|
||||
<string name="review_is_uploaded_by">%1$s is uploaded by: %2$s</string>
|
||||
<string name="default_description_language">Default description language</string>
|
||||
<string name="secondary_description_languages">Secondary Description Language</string>
|
||||
<string name="delete_helper_show_deletion_title">Nominating for deletion</string>
|
||||
<string name="delete_helper_show_deletion_title_success">Success</string>
|
||||
<string name="delete_helper_show_deletion_message_if">Nominated %1$s for deletion.</string>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,13 @@
|
|||
app:singleLineTitle="false"
|
||||
android:title="@string/default_description_language" />
|
||||
|
||||
<!-- New Secondary Language Picker -->
|
||||
<Preference
|
||||
android:key="descriptionSecondaryLanguagesPref"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
app:singleLineTitle="false"
|
||||
android:title="@string/secondary_description_languages" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="displayNearbyCardView"
|
||||
|
|
|
|||
|
|
@ -19,11 +19,13 @@ WHERE {
|
|||
|
||||
# Get the label in the preferred language of the user, or any other language if no label is available in that language.
|
||||
OPTIONAL {?item rdfs:label ?itemLabelPreferredLanguage. FILTER (lang(?itemLabelPreferredLanguage) = "${LANG}")}
|
||||
${SECONDARYLABEL}
|
||||
OPTIONAL {?item rdfs:label ?itemLabelAnyLanguage}
|
||||
BIND(COALESCE(?itemLabelPreferredLanguage, ?itemLabelAnyLanguage, "?") as ?label)
|
||||
|
||||
# Get the description in the preferred language of the user, or any other language if no description is available in that language.
|
||||
OPTIONAL {?item schema:description ?itemDescriptionPreferredLanguage. FILTER (lang(?itemDescriptionPreferredLanguage) = "${LANG}")}
|
||||
${SECONDARYDESCRIPTION}
|
||||
OPTIONAL {?item schema:description ?itemDescriptionAnyLanguage}
|
||||
BIND(COALESCE(?itemDescriptionPreferredLanguage, ?itemDescriptionAnyLanguage, "?") as ?description)
|
||||
|
||||
|
|
@ -31,6 +33,7 @@ WHERE {
|
|||
OPTIONAL {
|
||||
?item p:P31/ps:P31 ?class.
|
||||
OPTIONAL {?class rdfs:label ?classLabelPreferredLanguage. FILTER (lang(?classLabelPreferredLanguage) = "${LANG}")}
|
||||
${SECONDARYCLASSLABEL}
|
||||
OPTIONAL {?class rdfs:label ?classLabelAnyLanguage}
|
||||
BIND(COALESCE(?classLabelPreferredLanguage, ?classLabelAnyLanguage, "?") as ?classLabel)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue