diff --git a/src/Models/Denomination.ts b/src/Models/Denomination.ts index 659cc9a11..487d36c7a 100644 --- a/src/Models/Denomination.ts +++ b/src/Models/Denomination.ts @@ -64,7 +64,7 @@ export class Denomination { throw `${context} uses the old 'default'-key. Use "useIfNoUnitGiven" or "useAsDefaultInput" instead` } - const humanTexts = Translations.T(json.human) + const humanTexts = typeof json.human === "string" ? Translations.T(json.human) : new Translation(json.human) humanTexts.OnEveryLanguage((text, language) => { if (text.indexOf("{quantity}") < 0) { throw `In denomination: a human text should contain {quantity} (at ${context}.human.${language}). The offending text is: ${text}` diff --git a/src/Models/ThemeConfig/Conversion/FixImages.ts b/src/Models/ThemeConfig/Conversion/FixImages.ts index 1eca0e2a9..eb680177e 100644 --- a/src/Models/ThemeConfig/Conversion/FixImages.ts +++ b/src/Models/ThemeConfig/Conversion/FixImages.ts @@ -190,10 +190,7 @@ export class ExtractImages extends Conversion< if (!allRenderedValuesAreImages && isImage) { // Extract images from the translations allFoundImages.push( - ...Translations.T( - img.leaf, - "extract_images from " + img.path.join(".") - ) + ...Translations.T(img.leaf) .ExtractImages(false) .map((path) => ({ path, diff --git a/src/Models/Unit.ts b/src/Models/Unit.ts index 9004dfc2f..a7e5428b7 100644 --- a/src/Models/Unit.ts +++ b/src/Models/Unit.ts @@ -1,7 +1,8 @@ -import BaseUIElement from "../UI/BaseUIElement" import { Denomination } from "./Denomination" import { Validator } from "../UI/InputElement/Validator" import FloatValidator from "../UI/InputElement/Validators/FloatValidator" +import { Translation } from "../UI/i18n/Translation" +import Translations from "../UI/i18n/Translations" export class Unit { public readonly appliesToKeys: Set @@ -109,7 +110,7 @@ export class Unit { return [undefined, undefined] } - asHumanLongValue(value: string | number, country: () => string): BaseUIElement | string { + asHumanLongValue(value: string | number, country: () => string): Translation { if (value === undefined) { return undefined } @@ -120,10 +121,10 @@ export class Unit { return human.Subs({ quantity: stripped + "/" }) } if (stripped === "1") { - return denom?.humanSingular ?? stripped + return Translations.T(denom?.humanSingular ?? stripped) } if (human === undefined) { - return stripped ?? value + return Translations.T(stripped ?? value) } return human.Subs({ quantity: stripped }) @@ -173,7 +174,6 @@ export class Unit { /** * Gets the value in the canonical denomination; * e.g. "1cm -> 0.01" as it is 0.01meter - * @param v */ public valueInCanonical(value: string, country: () => string): number { const denom = this.findDenomination(value, country) diff --git a/src/UI/Base/TrDyn.svelte b/src/UI/Base/TrDyn.svelte new file mode 100644 index 000000000..d84619ffc --- /dev/null +++ b/src/UI/Base/TrDyn.svelte @@ -0,0 +1,9 @@ + + + diff --git a/src/UI/Popup/DataVisualisations.ts b/src/UI/Popup/DataVisualisations.ts index 1cc80257e..4df4c45c7 100644 --- a/src/UI/Popup/DataVisualisations.ts +++ b/src/UI/Popup/DataVisualisations.ts @@ -2,7 +2,7 @@ import { SpecialVisualisationArg, SpecialVisualisationParams, SpecialVisualization, - SpecialVisualizationSvelte, + SpecialVisualizationSvelte } from "../SpecialVisualization" import { HistogramViz } from "./HistogramViz" import { Store } from "../../Logic/UIEventSource" @@ -32,6 +32,8 @@ import Marker from "../Map/Marker.svelte" import { twJoin } from "tailwind-merge" import { Tag } from "../../Logic/Tags/Tag" import { Lists } from "../../Utils/Lists" +import { Translation } from "../i18n/Translation" +import TrDyn from "../Base/TrDyn.svelte" class DirectionIndicatorVis extends SpecialVisualizationSvelte { funcName = "direction_indicator" @@ -46,7 +48,7 @@ class DirectionIndicatorVis extends SpecialVisualizationSvelte { } } -class DirectionAbsolute extends SpecialVisualization { +class DirectionAbsolute extends SpecialVisualizationSvelte { funcName = "direction_absolute" docs = "Converts compass degrees (with 0° being north, 90° being east, ...) into a human readable, translated direction such as 'north', 'northeast'" @@ -65,24 +67,20 @@ class DirectionAbsolute extends SpecialVisualization { ] group = "data" - constr({ tags, args }: SpecialVisualisationParams): BaseUIElement { + constr({ tags, args }: SpecialVisualisationParams): SvelteUIElement { const key = args[0] === "" ? "_direction:centerpoint" : args[0] const offset = args[1] === "" ? 0 : Number(args[1]) - return new VariableUiElement( - tags - .map((tags) => { - console.log("Direction value", tags[key], key) - return tags[key] - }) - .mapD((value) => { - const dir = GeoOperations.bearingToHuman( - GeoOperations.parseBearing(value) + offset - ) - console.log("Human dir", dir) - return Translations.t.general.visualFeedback.directionsAbsolute[dir] - }) - ) + const t: Store = tags + .map((tags) => tags[key]) + .mapD((value: string) => { + const dir = GeoOperations.bearingToHuman( + GeoOperations.parseBearing(value) + offset + ) + return Translations.t.general.visualFeedback.directionsAbsolute[dir] + }) + + return new SvelteUIElement(TrDyn, { t }) } } @@ -162,7 +160,7 @@ class OpeningHoursState extends SpecialVisualizationSvelte { } } -class Canonical extends SpecialVisualization { +class Canonical extends SpecialVisualizationSvelte { group = "data" funcName = "canonical" @@ -181,24 +179,23 @@ class Canonical extends SpecialVisualization { constr({ state, tags, args }: SpecialVisualisationParams) { const key = args[0] - return new VariableUiElement( - tags - .map((tags) => tags[key]) - .map((value) => { - if (value === undefined) { - return undefined - } - const allUnits: Unit[] = [].concat( - ...(state?.theme?.layers?.map((lyr) => lyr.units) ?? []) - ) - const unit = allUnits.filter((unit) => unit.isApplicableToKey(key))[0] - if (unit === undefined) { - return value - } - const getCountry = () => tags.data._country - return unit.asHumanLongValue(value, getCountry) - }) - ) + const t: Store = tags + .map((tags) => tags[key]) + .map((value: string) => { + if (value === undefined) { + return undefined + } + const allUnits: Unit[] = [].concat( + ...(state?.theme?.layers?.map((lyr) => lyr.units) ?? []) + ) + const unit = allUnits.filter((unit) => unit.isApplicableToKey(key))[0] + if (unit === undefined) { + return Translations.T(value) + } + const getCountry = () => tags.data._country + return unit.asHumanLongValue(value, getCountry) + }) + return new SvelteUIElement(TrDyn, { t }) } } diff --git a/src/UI/SpecialVisualisations/UISpecialVisualisations.ts b/src/UI/SpecialVisualisations/UISpecialVisualisations.ts index 0b7277d8d..40d9a5513 100644 --- a/src/UI/SpecialVisualisations/UISpecialVisualisations.ts +++ b/src/UI/SpecialVisualisations/UISpecialVisualisations.ts @@ -1,13 +1,6 @@ -import { - SpecialVisualisationParams, - SpecialVisualization, - SpecialVisualizationState, - SpecialVisualizationSvelte, -} from "../SpecialVisualization" +import { SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationSvelte } from "../SpecialVisualization" import SvelteUIElement from "../Base/SvelteUIElement" -import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource" -import { Feature, GeoJSON } from "geojson" -import LayerConfig from "../../Models/ThemeConfig/LayerConfig" +import { ImmutableStore, Store } from "../../Logic/UIEventSource" import Questionbox from "../Popup/TagRendering/Questionbox.svelte" import MinimapViz from "../Popup/MinimapViz.svelte" import SplitRoadWizard from "../Popup/SplitRoadWizard.svelte" @@ -19,11 +12,11 @@ import { ShareLinkViz } from "../Popup/ShareLinkViz" import { GeoOperations } from "../../Logic/GeoOperations" import AddNewPoint from "../Popup/AddNewPoint/AddNewPoint.svelte" import BaseUIElement from "../BaseUIElement" -import { VariableUiElement } from "../Base/VariableUIElement" import { Translation } from "../i18n/Translation" import { FixedUiElement } from "../Base/FixedUiElement" import { default as FeatureTitle } from "../Popup/Title.svelte" import CreateCopy from "../Popup/AddNewPoint/CreateCopy.svelte" +import TrDyn from "../Base/TrDyn.svelte" /** * Thin wrapper around QuestionBox.svelte to include it into the special Visualisations @@ -105,7 +98,7 @@ class Minimap extends SpecialVisualizationSvelte { example = "`{minimap()}`, `{minimap(17, id, _list_of_embedded_feature_ids_calculated_by_calculated_tag):height:10rem; border: 2px solid black}`" - constr({ state, tags, args, feature, layer }: SpecialVisualisationParams): SvelteUIElement { + constr({ state, tags, args, feature }: SpecialVisualisationParams): SvelteUIElement { const minzoom = Number(args[0] ?? 18) const ids = args[1]?.split(";")?.map((s) => s.trim()) ?? ["id"] const clss = args[2] @@ -263,18 +256,18 @@ class Translated extends SpecialVisualization { ] constr({ tags, args }: SpecialVisualisationParams): BaseUIElement { - return new VariableUiElement( - tags.map((tags) => { - const v = tags[args[0] ?? "value"] - try { - const tr = typeof v === "string" ? JSON.parse(v) : v - return new Translation(tr).SetClass("font-bold") - } catch (e) { - console.error("Cannot create a translation for", v, "due to", e) - return JSON.stringify(v) - } - }) - ) + + const t: Store = tags.map((tags) => { + const v = tags[args[0] ?? "value"] + try { + const tr = typeof v === "string" ? JSON.parse(v) : v + return new Translation(tr) + } catch (e) { + console.error("Cannot create a translation for", v, "due to", e) + return new Translation({ "*": JSON.stringify(v) }) + } + }) + return new SvelteUIElement(TrDyn, { t }) } } diff --git a/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts b/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts index 48033f9de..8f88d3b2d 100644 --- a/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts +++ b/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts @@ -1,21 +1,18 @@ -import { - SpecialVisualisationParams, - SpecialVisualization, - SpecialVisualizationSvelte, -} from "../SpecialVisualization" +import { SpecialVisualisationParams, SpecialVisualizationSvelte } from "../SpecialVisualization" import { ImmutableStore, Store } from "../../Logic/UIEventSource" import SvelteUIElement from "../Base/SvelteUIElement" import FediverseLink from "../Popup/FediverseLink.svelte" import Wikidata, { WikidataResponse } from "../../Logic/Web/Wikidata" import Wikipedia from "../../Logic/Web/Wikipedia" import WikipediaPanel from "../Wikipedia/WikipediaPanel.svelte" -import { VariableUiElement } from "../Base/VariableUIElement" import { Utils } from "../../Utils" import { Translation } from "../i18n/Translation" import { MapillaryLinkVis } from "../Popup/MapillaryLinkVis" import SendEmail from "../Popup/SendEmail.svelte" import DynLink from "../Base/DynLink.svelte" import { Lists } from "../../Utils/Lists" +import TrDyn from "../Base/TrDyn.svelte" +import Translations from "../i18n/Translations" class FediverseLinkVis extends SpecialVisualizationSvelte { funcName = "fediverse_link" @@ -65,7 +62,7 @@ class WikipediaVis extends SpecialVisualizationSvelte { } } -class WikidatalabelVis extends SpecialVisualization { +class WikidatalabelVis extends SpecialVisualizationSvelte { funcName = "wikidata_label" group = "web_and_communication" @@ -84,25 +81,25 @@ class WikidatalabelVis extends SpecialVisualization { "`{wikidata_label()}` is a basic example, `{wikipedia(name:etymology:wikidata)}` to show the label itself" constr({ tags, args }: SpecialVisualisationParams) { - const id = tags + const id: Store = tags .map((tags) => tags[args[0]]) .map((wikidata) => { const wikidataIds = Lists.noEmpty( wikidata?.split(";")?.map((wd) => wd.trim()) ?? [] ) - return wikidataIds?.[0] + return (wikidataIds?.[0]) }) - const entry = id.bind((id) => Wikidata.LoadWikidataEntry(id)) - - return new VariableUiElement( - entry.map((e) => { - if (e === undefined || e["success"] === undefined) { - return id.data - } - const response = e["success"] - return Translation.fromMap(response.labels) - }) - ) + const entry: Store<{ success: WikidataResponse } | { + error: any + }> = id.bind((id) => Wikidata.LoadWikidataEntry(id)) + const t: Store = entry.map((e) => { + if (e === undefined || e["success"] === undefined) { + return Translations.T(id.data) + } + const response = e["success"] + return Translation.fromMap(response.labels) + }) + return new SvelteUIElement(TrDyn, { t }) } } @@ -199,7 +196,7 @@ class LinkVis extends SpecialVisualizationSvelte { } } export class WebAndCommunicationSpecialVisualisations { - public static initList(): SpecialVisualization[] { + public static initList(): SpecialVisualizationSvelte[] { return [ new FediverseLinkVis(), new WikipediaVis(), diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index 5f44e7800..9f78a8710 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -1,8 +1,4 @@ -import { - RenderingSpecification, - SpecialVisualization, - SpecialVisualizationSvelte, -} from "./SpecialVisualization" +import { RenderingSpecification, SpecialVisualization, SpecialVisualizationSvelte } from "./SpecialVisualization" import { UploadToOsmViz } from "./Popup/UploadToOsmViz" import { MultiApplyViz } from "./Popup/MultiApplyViz" import AutoApplyButtonVis from "./Popup/AutoApplyButtonVis" @@ -15,8 +11,11 @@ import { UISpecialVisualisations } from "./SpecialVisualisations/UISpecialVisual import { SettingsVisualisations } from "./SpecialVisualisations/SettingsVisualisations" import { ReviewSpecialVisualisations } from "./SpecialVisualisations/ReviewSpecialVisualisations" import { DataImportSpecialVisualisations } from "./SpecialVisualisations/DataImportSpecialVisualisations" -import TagrenderingManipulationSpecialVisualisations from "./SpecialVisualisations/TagrenderingManipulationSpecialVisualisations" -import { WebAndCommunicationSpecialVisualisations } from "./SpecialVisualisations/WebAndCommunicationSpecialVisualisations" +import TagrenderingManipulationSpecialVisualisations + from "./SpecialVisualisations/TagrenderingManipulationSpecialVisualisations" +import { + WebAndCommunicationSpecialVisualisations +} from "./SpecialVisualisations/WebAndCommunicationSpecialVisualisations" import { DataVisualisations } from "./Popup/DataVisualisations" import { DataExportVisualisations } from "./Popup/DataExportVisualisations" import { Utils } from "../Utils" @@ -186,6 +185,7 @@ export default class SpecialVisualizations { ...SettingsVisualisations.initList(), ...DataImportSpecialVisualisations.initList(), ...DataExportVisualisations.initList(), + ...WebAndCommunicationSpecialVisualisations.initList(), new UploadToOsmViz(), new MultiApplyViz(), ] @@ -195,7 +195,6 @@ export default class SpecialVisualizations { ...UISpecialVisualisations.initList(), ...ReviewSpecialVisualisations.initList(), ...TagrenderingManipulationSpecialVisualisations.initList(), - ...WebAndCommunicationSpecialVisualisations.initList(), ...DataVisualisations.initList(), ...specialVisualizationsSv, ]