Merge branch 'develop' into Robin-patch-1

This commit is contained in:
Robin van der Linde 2025-08-23 19:21:44 +02:00
commit 86d636366e
13 changed files with 2266 additions and 31 deletions

View file

@ -18,7 +18,7 @@ interface value<T> {
} }
interface LanguageSpecResult { interface LanguageSpecResult {
directionalityLabel: value<string | "right-to-left" | "left-to-right"> directionalityLabel?: value<string | "right-to-left" | "left-to-right">
lang: value<string> lang: value<string>
code: value<string> code: value<string>
label: value<string> label: value<string>
@ -77,6 +77,29 @@ async function fetchRegularLanguages() {
return result.results.bindings return result.results.bindings
} }
async function fetchSignLanguages() {
const query = `
SELECT ?lang ?label ?code
WHERE
{
?lang wdt:P31 wd:Q34228.
OPTIONAL {
?lang wdt:P1813 ?code.
}
?lang rdfs:label ?label.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}`
const url = Wikidata.wds.sparqlQuery(query)
// request the generated URL with your favorite HTTP request library
const result = await Utils.downloadJson<{ results: { bindings: any[] } }>(url, {
"User-Agent": "MapComplete script",
})
return <LanguageSpecResult[]>result.results.bindings
}
/** /**
* Fetches the object as is. Sets a 'code' binding as predifined value * Fetches the object as is. Sets a 'code' binding as predifined value
* @param id * @param id
@ -169,7 +192,20 @@ async function getOfficialLanguagesPerCountryCached(
return officialLanguages return officialLanguages
} }
async function generateSignLanguageOverview(){
const signLanguages = await fetchSignLanguages()
const signPerId = WikidataUtils.extractLanguageData(signLanguages, WikidataUtils.languageRemapping)
const asRecord : Record<string, Record<string, string>> = {}
for (const lng of signPerId.keys()) {
asRecord[lng.toLowerCase()] = Utils.MapToObj(signPerId.get(lng).translations)
}
return asRecord
}
async function main(wipeCache = false) { async function main(wipeCache = false) {
const signLanguages = await generateSignLanguageOverview()
const cacheFile = "./src/assets/generated/languages-wd.json" const cacheFile = "./src/assets/generated/languages-wd.json"
if (wipeCache || !existsSync(cacheFile)) { if (wipeCache || !existsSync(cacheFile)) {
console.log("Refreshing cache") console.log("Refreshing cache")
@ -181,7 +217,8 @@ async function main(wipeCache = false) {
const data = JSON.parse(readFileSync(cacheFile, { encoding: "utf8" })) const data = JSON.parse(readFileSync(cacheFile, { encoding: "utf8" }))
const perId = WikidataUtils.extractLanguageData(data, WikidataUtils.languageRemapping) const perId = WikidataUtils.extractLanguageData(data, WikidataUtils.languageRemapping)
const nativeList = getNativeList(perId) const nativeList = getNativeList(perId)
writeFileSync("./src/assets/language_native.json", JSON.stringify(nativeList, null, " ")) writeFileSync("./src/assets/language_native.json", JSON.stringify({ ...nativeList, ...signLanguages }, null, " "))
const languagesPerCountry = Utils.TransposeMap( const languagesPerCountry = Utils.TransposeMap(
await getOfficialLanguagesPerCountryCached(wipeCache) await getOfficialLanguagesPerCountryCached(wipeCache)
) )

View file

@ -11,6 +11,9 @@ import { Feature, Point } from "geojson"
import { AddImageOptions } from "panoramax-js/dist/Panoramax" import { AddImageOptions } from "panoramax-js/dist/Panoramax"
import { ServerSourceInfo } from "../../Models/SourceOverview" import { ServerSourceInfo } from "../../Models/SourceOverview"
import { ComponentType } from "svelte/types/runtime/internal/dev" import { ComponentType } from "svelte/types/runtime/internal/dev"
import { Strings } from "../../Utils/Strings"
import { Utils } from "../../Utils"
import { Lists } from "../../Utils/Lists"
export default class PanoramaxImageProvider extends ImageProvider { export default class PanoramaxImageProvider extends ImageProvider {
public static readonly singleton: PanoramaxImageProvider = new PanoramaxImageProvider() public static readonly singleton: PanoramaxImageProvider = new PanoramaxImageProvider()
@ -194,9 +197,13 @@ export default class PanoramaxImageProvider extends ImageProvider {
public async DownloadAttribution(providedImage: { id: string }): Promise<LicenseInfo> { public async DownloadAttribution(providedImage: { id: string }): Promise<LicenseInfo> {
const meta = await this.getInfoFor(providedImage.id) const meta = await this.getInfoFor(providedImage.id)
const artists = Lists.noEmpty(meta.data.providers.map(p => p.name))
// We take the last provider, as that one probably contain the username of the uploader
const artist = artists.at(-1)
return { return {
artist: meta.data.providers.at(-1).name, // We take the last provider, as that one probably contain the username of the uploader artist,
date: new Date(meta.data.properties["datetime"]), date: new Date(meta.data.properties["datetime"]),
licenseShortName: meta.data.properties["geovisio:license"], licenseShortName: meta.data.properties["geovisio:license"],
} }

View file

@ -76,7 +76,7 @@
value.set("") value.set("")
e.preventDefault() e.preventDefault()
}} }}
color="var(--button-background)" color="var(--foreground-color)"
class="mr-3 h-6 w-6 cursor-pointer" class="mr-3 h-6 w-6 cursor-pointer"
/> />
{:else} {:else}

View file

@ -231,7 +231,8 @@ export class PointRenderingLayer {
let store: Store<Record<string, string>> let store: Store<Record<string, string>>
if (this._fetchStore) { if (this._fetchStore) {
store = this._fetchStore(feature.properties.id) store = this._fetchStore(feature.properties.id)
} else { }
if(!store){
store = new ImmutableStore(<OsmTags>feature.properties) store = new ImmutableStore(<OsmTags>feature.properties)
} }
const { html, iconAnchor } = this._config.RenderIcon(store, { metatags: this._metatags }) const { html, iconAnchor } = this._config.RenderIcon(store, { metatags: this._metatags })

View file

@ -17,8 +17,6 @@
import OpenBackgroundSelectorButton from "../../BigComponents/OpenBackgroundSelectorButton.svelte" import OpenBackgroundSelectorButton from "../../BigComponents/OpenBackgroundSelectorButton.svelte"
import Tr from "../../Base/Tr.svelte" import Tr from "../../Base/Tr.svelte"
import ThemeViewState from "../../../Models/ThemeViewState" import ThemeViewState from "../../../Models/ThemeViewState"
import TagExplanation from "../TagExplanation.svelte"
import { And } from "../../../Logic/Tags/And"
import Loading from "../../Base/Loading.svelte" import Loading from "../../Base/Loading.svelte"
import CreateNewNodeAction from "../../../Logic/Osm/Actions/CreateNewNodeAction" import CreateNewNodeAction from "../../../Logic/Osm/Actions/CreateNewNodeAction"
import DocumentDuplicate from "@babeard/svelte-heroicons/solid/DocumentDuplicate" import DocumentDuplicate from "@babeard/svelte-heroicons/solid/DocumentDuplicate"
@ -26,6 +24,7 @@
import { EyeOffIcon } from "@rgossiaux/svelte-heroicons/solid" import { EyeOffIcon } from "@rgossiaux/svelte-heroicons/solid"
import Layers from "../../../assets/svg/Layers.svelte" import Layers from "../../../assets/svg/Layers.svelte"
import { onDestroy } from "svelte" import { onDestroy } from "svelte"
import TagHint from "../TagHint.svelte"
export let state: ThemeViewState export let state: ThemeViewState
export let layer: LayerConfig export let layer: LayerConfig
@ -180,7 +179,7 @@
</div> </div>
{#if showTags} {#if showTags}
<div class="subtle"> <div class="subtle">
<TagExplanation tagsFilter={new And($asTags)} linkToWiki /> <TagHint tags={$asTags} />
</div> </div>
{/if} {/if}
</div> </div>

View file

@ -42,7 +42,7 @@
{#if $foundLanguages.length === 0 && on_no_known_languages && !$forceInputMode} {#if $foundLanguages.length === 0 && on_no_known_languages && !$forceInputMode}
<div class="low-interaction flex items-center justify-between rounded p-1"> <div class="low-interaction flex items-center justify-between rounded p-1">
<div> <div class="ml-1">
{on_no_known_languages} {on_no_known_languages}
</div> </div>
<EditButton on:click={(_) => forceInputMode.setData(true)} /> <EditButton on:click={(_) => forceInputMode.setData(true)} />

View file

@ -7,7 +7,7 @@ export class LanguageElement extends SpecialVisualizationSvelte {
needsUrls = [] needsUrls = []
docs: string = docs: string =
"The language element allows to show and pick all known (modern) languages. The key can be set" "The language element allows to show and pick all known (modern) languages (includes sign languages). The key can be set"
args: { args: {
name: string name: string

View file

@ -106,7 +106,7 @@
<Tr t={Translations.t.general.useSearch} /> <Tr t={Translations.t.general.useSearch} />
</label> </label>
<div class="overflow-auto" style="max-height: 25vh"> <div style="max-height: 25vh">
{#each knownLanguagecodes as lng} {#each knownLanguagecodes as lng}
{#if isChecked[lng] && $newlyChecked.indexOf(lng) < 0 && probableLanguages.indexOf(lng) < 0} {#if isChecked[lng] && $newlyChecked.indexOf(lng) < 0 && probableLanguages.indexOf(lng) < 0}
<label class="no-image-background flex items-center gap-1"> <label class="no-image-background flex items-center gap-1">

View file

@ -21,6 +21,7 @@
import { Tag } from "../../../Logic/Tags/Tag" import { Tag } from "../../../Logic/Tags/Tag"
import ChangeTagAction from "../../../Logic/Osm/Actions/ChangeTagAction" import ChangeTagAction from "../../../Logic/Osm/Actions/ChangeTagAction"
import { And } from "../../../Logic/Tags/And" import { And } from "../../../Logic/Tags/And"
import TagHint from "../TagHint.svelte"
export let question: string export let question: string
export let prefix: string export let prefix: string
@ -67,6 +68,10 @@
} }
dispatch("save") dispatch("save")
} }
const showTags = state.userRelatedState.showTagsB
// For the preview
let asTags = selectedLanguages.mapD(lngs => lngs.map((ln) => new Tag(prefix + ln, "yes")))
</script> </script>
<div class="disable-links interactive border-interactive flex flex-col p-2"> <div class="disable-links interactive border-interactive flex flex-col p-2">
@ -74,7 +79,6 @@
<SpecialTranslation {feature} {layer} {state} t={new Translation({ "*": question })} {tags} /> <SpecialTranslation {feature} {layer} {state} t={new Translation({ "*": question })} {tags} />
</div> </div>
<LanguageOptions {selectedLanguages} countries={$countries} /> <LanguageOptions {selectedLanguages} countries={$countries} />
<div class="flex w-full flex-wrap-reverse justify-end"> <div class="flex w-full flex-wrap-reverse justify-end">
<slot name="cancel-button" /> <slot name="cancel-button" />
<button <button
@ -85,4 +89,9 @@
<Tr t={Translations.t.general.save} /> <Tr t={Translations.t.general.save} />
</button> </button>
</div> </div>
{#if showTags}
<div class="subtle w-fit">
<TagHint tags={$asTags} />
</div>
{/if}
</div> </div>

View file

@ -1,15 +0,0 @@
<script lang="ts">
/**
* Shows an explanation about the given TagsFilter.
*/
import { TagsFilter } from "../../Logic/Tags/TagsFilter"
import FromHtml from "../Base/FromHtml.svelte"
export let tagsFilter: TagsFilter
export let properties: Record<string, string> | undefined = {}
export let linkToWiki: boolean = false
</script>
{#if tagsFilter !== undefined}
<FromHtml src={tagsFilter.asHumanString(linkToWiki, false, properties)} />
{/if}

View file

@ -7,9 +7,9 @@
import Loading from "../Base/Loading.svelte" import Loading from "../Base/Loading.svelte"
import TagApplyViz from "./TagApplyViz" import TagApplyViz from "./TagApplyViz"
import Icon from "../Map/Icon.svelte" import Icon from "../Map/Icon.svelte"
import TagExplanation from "../Popup/TagExplanation.svelte"
import { And } from "../../Logic/Tags/And" import { And } from "../../Logic/Tags/And"
import Translations from "../i18n/Translations" import Translations from "../i18n/Translations"
import TagHint from "../Popup/TagHint.svelte"
/** /**
* Works closely together with 'TagApplyViz * Works closely together with 'TagApplyViz
@ -53,7 +53,7 @@
})} })}
/> />
{:else} {:else}
<TagExplanation tagsFilter={new And($tagsToApply)} /> <TagHint tags={$tagsToApply} />
{/if} {/if}
</div> </div>
</button> </button>

View file

@ -30,7 +30,11 @@ export default class WikidataUtils {
{ translations: Map<string, string>; directionality?: string[] } { translations: Map<string, string>; directionality?: string[] }
>() >()
for (const element of data) { for (const element of data) {
let id = element.code.value let id = element.code?.value
if(!id){
console.warn("No language code for", JSON.stringify(element),"ignoring")
continue
}
id = remapLanguages[id] ?? id id = remapLanguages[id] ?? id
let labelLang = element.label["xml:lang"] let labelLang = element.label["xml:lang"]
labelLang = remapLanguages[labelLang] ?? labelLang labelLang = remapLanguages[labelLang] ?? labelLang

File diff suppressed because it is too large Load diff