Move image license picker into user panel, fix #1236

This commit is contained in:
Pieter Vander Vennet 2023-01-11 03:53:58 +01:00
parent 6a5e7f9a4d
commit a995f0e2aa
35 changed files with 252 additions and 303 deletions

View file

@ -8,7 +8,6 @@ import Img from "../../UI/Base/Img"
import { Utils } from "../../Utils"
import { OsmObject } from "./OsmObject"
import { Changes } from "./Changes"
import ScriptUtils from "../../scripts/ScriptUtils"
export default class UserDetails {
public loggedIn = false

View file

@ -144,6 +144,14 @@ export class OsmPreferences {
this.UploadPreference(key, v)
})
this.preferences.addCallbackD((allPrefs) => {
const v = allPrefs[key]
if (v === undefined) {
return
}
pref.setData(v)
})
this.preferenceSources.set(key, pref)
return pref
}
@ -220,6 +228,7 @@ export class OsmPreferences {
if (this.preferences.data[k] === v) {
return
}
const self = this
console.debug("Updating preference", k, " to ", Utils.EllipsesAfter(v, 15))
if (v === undefined || v === "") {
@ -234,6 +243,8 @@ export class OsmPreferences {
console.warn("Could not remove preference", error)
return
}
delete self.preferences.data[k]
self.preferences.ping()
console.debug("Preference ", k, "removed!")
}
)
@ -252,6 +263,8 @@ export class OsmPreferences {
console.warn(`Could not set preference "${k}"'`, error)
return
}
self.preferences.data[k] = v
self.preferences.ping()
console.debug(`Preference ${k} written!`)
}
)

View file

@ -109,6 +109,7 @@ export default class Constants {
static zoomToLocationTimeout = 60
static countryCoderEndpoint: string =
"https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/latlon2country"
public static readonly OsmPreferenceKeyPicturesLicense = "pictures-license"
private static isRetina(): boolean {
if (Utils.runningFromConsole) {

View file

@ -86,7 +86,7 @@ export default class TagRenderingConfig {
let translationKey = context
if (json["id"] !== undefined) {
const layerId = context.split(".")[0]
const layerId = (context ?? "").split(".")[0]
if (json["source"]) {
let src = json["source"] + ":"
if (json["source"] === "shared-questions") {

View file

@ -1,38 +0,0 @@
import { DropDown } from "../Input/DropDown"
import Translations from "../i18n/Translations"
import { UIEventSource } from "../../Logic/UIEventSource"
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import { Translation } from "../i18n/Translation"
export default class LicensePicker extends DropDown<string> {
private static readonly cc0 = "CC0"
private static readonly ccbysa = "CC-BY-SA 4.0"
private static readonly ccby = "CC-BY 4.0"
constructor(state: { osmConnection: OsmConnection }) {
super(
Translations.t.image.willBePublished.Clone(),
[
{ value: LicensePicker.cc0, shown: Translations.t.image.cco.Clone() },
{ value: LicensePicker.ccbysa, shown: Translations.t.image.ccbs.Clone() },
{ value: LicensePicker.ccby, shown: Translations.t.image.ccb.Clone() },
],
state?.osmConnection?.GetPreference("pictures-license") ??
new UIEventSource<string>("CC0"),
{
select_class: "w-min bg-indigo-100 p-1 rounded hover:bg-indigo-200",
}
)
this.SetClass("flex flex-col sm:flex-row").SetStyle("float:left")
}
public static LicenseExplanations(): Map<string, Translation> {
let dict = new Map<string, Translation>()
dict.set(LicensePicker.cc0, Translations.t.image.ccoExplanation)
dict.set(LicensePicker.ccby, Translations.t.image.ccbExplanation)
dict.set(LicensePicker.ccbysa, Translations.t.image.ccbsExplanation)
return dict
}
}

View file

@ -15,6 +15,12 @@ import Showdown from "showdown"
import LanguagePicker from "../LanguagePicker"
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
import Constants from "../../Models/Constants"
import EditableTagRendering from "../Popup/EditableTagRendering"
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
import { SaveButton } from "../Popup/SaveButton"
import { TagUtils } from "../../Logic/Tags/TagUtils"
import * as questions from "../../assets/tagRenderings/questions.json"
import { TagRenderingConfigJson } from "../../Models/ThemeConfig/Json/TagRenderingConfigJson"
export class ImportViewerLinks extends VariableUiElement {
constructor(osmConnection: OsmConnection) {
@ -36,7 +42,7 @@ export class ImportViewerLinks extends VariableUiElement {
}
}
class UserInformationMainPanel extends Combine {
class UserInformationMainPanel extends VariableUiElement {
constructor(
osmConnection: OsmConnection,
locationControl: UIEventSource<Loc>,
@ -46,96 +52,125 @@ class UserInformationMainPanel extends Combine {
const t = Translations.t.userinfo
const imgSize = "h-6 w-6"
const ud = osmConnection.userDetails
super([
new VariableUiElement(
ud.map((ud) => {
if (!ud?.loggedIn) {
// Not logged in
return new SubtleButton(Svg.login_svg(), "Login", { imgSize }).onClick(() =>
osmConnection.AttemptLogin()
)
}
super(
ud.map((ud) => {
if (!ud?.loggedIn) {
// Not logged in
return new SubtleButton(Svg.login_svg(), "Login", { imgSize }).onClick(() =>
osmConnection.AttemptLogin()
)
}
let img: Img = Svg.person_svg()
if (ud.img !== undefined) {
img = new Img(ud.img)
}
img.SetClass("rounded-full h-12 w-12 m-4")
let img: Img = Svg.person_svg()
if (ud.img !== undefined) {
img = new Img(ud.img)
}
img.SetClass("rounded-full h-12 w-12 m-4")
let description: BaseUIElement = undefined
if (ud.description) {
const editButton = new Link(
Svg.pencil_svg().SetClass("h-4 w-4"),
"https://www.openstreetmap.org/profile/edit",
true
).SetClass(
"absolute block bg-subtle rounded-full p-2 bottom-2 right-2 w-min self-end"
)
let description: BaseUIElement = undefined
if (ud.description) {
const editButton = new Link(
Svg.pencil_svg().SetClass("h-4 w-4"),
"https://www.openstreetmap.org/profile/edit",
true
).SetClass(
"absolute block bg-subtle rounded-full p-2 bottom-2 right-2 w-min self-end"
)
description = new Combine([
new FixedUiElement(
new Showdown.Converter().makeHtml(ud.description)
).SetClass("link-underline"),
editButton,
]).SetClass("relative w-full m-2")
} else {
description = new Combine([
t.noDescription,
new SubtleButton(Svg.pencil_svg(), t.noDescriptionCallToAction, {
imgSize,
description = new Combine([
new FixedUiElement(
new Showdown.Converter().makeHtml(ud.description)
).SetClass("link-underline"),
editButton,
]).SetClass("relative w-full m-2")
} else {
description = new Combine([
t.noDescription,
new SubtleButton(Svg.pencil_svg(), t.noDescriptionCallToAction, {
imgSize,
}),
]).SetClass("w-full m-2")
}
let panToHome: BaseUIElement
if (ud.home) {
panToHome = new SubtleButton(Svg.home_svg(), t.moveToHome, {
imgSize,
}).onClick(() => {
const home = ud?.home
if (home === undefined) {
return
}
locationControl.setData({ ...home, zoom: 16 })
isOpened.setData(false)
})
}
const editMode = new UIEventSource(false)
const licensePicker = new EditableTagRendering(
osmConnection.preferencesHandler.preferences,
new TagRenderingConfig(
<TagRenderingConfigJson>{
source: "shared-questions",
...questions["picture-license"],
},
"shared-questions"
),
[],
{ osmConnection },
{
editMode,
createSaveButton: (store) =>
new SaveButton(
osmConnection.preferencesHandler.preferences,
osmConnection
).onClick(() => {
const prefs = osmConnection.preferencesHandler.preferences
const selection = TagUtils.FlattenMultiAnswer(
TagUtils.FlattenAnd(store.data, prefs.data)
).asChange(prefs.data)
for (const kv of selection) {
osmConnection.GetPreference(kv.k, "", "").setData(kv.v)
}
editMode.setData(false)
}),
]).SetClass("w-full m-2")
}
)
let panToHome: BaseUIElement
if (ud.home) {
panToHome = new SubtleButton(Svg.home_svg(), t.moveToHome, {
imgSize,
}).onClick(() => {
const home = ud?.home
if (home === undefined) {
return
}
locationControl.setData({ ...home, zoom: 16 })
isOpened.setData(false)
})
}
return new Combine([
new Combine([img, description]).SetClass(
"flex border border-black rounded-md"
),
new LanguagePicker(
layout.language,
Translations.t.general.pickLanguage.Clone()
),
new SubtleButton(
Svg.envelope_svg(),
new Combine([
t.gotoInbox,
ud.unreadMessages == 0
? undefined
: t.newMessages.SetClass("alert block"),
]),
{ imgSize, url: `${ud.backend}/messages/inbox`, newTab: true }
),
new SubtleButton(Svg.gear_svg(), t.gotoSettings, {
imgSize,
url: `${ud.backend}/user/${encodeURIComponent(ud.name)}/account`,
newTab: true,
}),
panToHome,
new ImportViewerLinks(osmConnection),
new SubtleButton(Svg.logout_svg(), Translations.t.general.logout, {
imgSize,
}).onClick(() => {
osmConnection.LogOut()
}),
])
})
).SetClass("flex flex-col"),
])
return new Combine([
new Combine([img, description]).SetClass("flex border border-black rounded-md"),
new LanguagePicker(
layout.language,
Translations.t.general.pickLanguage.Clone()
),
licensePicker.SetClass("block my-4"),
new SubtleButton(
Svg.envelope_svg(),
new Combine([
t.gotoInbox,
ud.unreadMessages == 0
? undefined
: t.newMessages.SetClass("alert block"),
]),
{ imgSize, url: `${ud.backend}/messages/inbox`, newTab: true }
),
new SubtleButton(Svg.gear_svg(), t.gotoSettings, {
imgSize,
url: `${ud.backend}/user/${encodeURIComponent(ud.name)}/account`,
newTab: true,
}),
panToHome,
new ImportViewerLinks(osmConnection),
new SubtleButton(Svg.logout_svg(), Translations.t.general.logout, {
imgSize,
}).onClick(() => {
osmConnection.LogOut()
}),
])
})
)
this.SetClass("flex flex-col")
}
}

View file

@ -4,7 +4,6 @@ import Translations from "../i18n/Translations"
import Svg from "../../Svg"
import { Tag } from "../../Logic/Tags/Tag"
import BaseUIElement from "../BaseUIElement"
import LicensePicker from "../BigComponents/LicensePicker"
import Toggle from "../Input/Toggle"
import FileSelectorButton from "../Input/FileSelectorButton"
import ImgurUploader from "../../Logic/ImageProviders/ImgurUploader"
@ -17,6 +16,7 @@ import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import { Changes } from "../../Logic/Osm/Changes"
import Loading from "../Base/Loading"
import { LoginToggle } from "../Popup/LoginButton"
import Constants from "../../Models/Constants"
export class ImageUploadFlow extends Toggle {
private static readonly uploadCountsPerId = new Map<string, UIEventSource<number>>()
@ -62,12 +62,6 @@ export class ImageUploadFlow extends Toggle {
uploadedCount.ping()
})
const licensePicker = new LicensePicker(state)
const explanations = LicensePicker.LicenseExplanations()
const chosenLicense = new VariableUiElement(
licensePicker.GetValue().map((license) => explanations.get(license))
)
const t = Translations.t.image
let labelContent: BaseUIElement
@ -108,7 +102,11 @@ export class ImageUploadFlow extends Toggle {
}
console.log("Received images from the user, starting upload")
const license = licensePicker.GetValue()?.data ?? "CC0"
const license =
state?.osmConnection?.GetPreference(
Constants.OsmPreferenceKeyPicturesLicense,
"CC0"
)?.data ?? "CC0"
const tags = tagsSource.data
@ -177,8 +175,6 @@ export class ImageUploadFlow extends Toggle {
fileSelector,
Translations.t.image.respectPrivacy.Clone().SetStyle("font-size:small;"),
licensePicker,
chosenLicense.SetClass("subtle text-sm"),
]).SetClass("flex flex-col image-upload-flow mt-4 mb-8 text-center")
super(

View file

@ -1,4 +1,4 @@
import { UIEventSource } from "../../Logic/UIEventSource"
import { Store, UIEventSource } from "../../Logic/UIEventSource"
import TagRenderingQuestion from "./TagRenderingQuestion"
import Translations from "../i18n/Translations"
import Combine from "../Base/Combine"
@ -9,7 +9,9 @@ import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
import { Unit } from "../../Models/Unit"
import Lazy from "../Base/Lazy"
import { FixedUiElement } from "../Base/FixedUiElement"
import { EditButton } from "./SaveButton"
import { EditButton, SaveButton } from "./SaveButton"
import { TagsFilter } from "../../Logic/Tags/TagsFilter"
import { TagUtils, UploadableTag } from "../../Logic/Tags/TagUtils"
export default class EditableTagRendering extends Toggle {
constructor(
@ -20,6 +22,8 @@ export default class EditableTagRendering extends Toggle {
options: {
editMode?: UIEventSource<boolean>
innerElementClasses?: string
/* Default will apply the tags to the relevant object, only use in special cases */
createSaveButton?: (src: Store<UploadableTag>) => BaseUIElement
}
) {
// The tagrendering is hidden if:
@ -31,6 +35,7 @@ export default class EditableTagRendering extends Toggle {
(configuration?.condition?.matchesProperties(tags) ?? true)
)
const editMode = options.editMode ?? new UIEventSource<boolean>(false)
super(
new Lazy(() => {
let rendering = EditableTagRendering.CreateRendering(
@ -38,10 +43,11 @@ export default class EditableTagRendering extends Toggle {
tags,
configuration,
units,
editMode
editMode,
{ saveButtonConstructor: options?.createSaveButton }
)
rendering.SetClass(options.innerElementClasses)
if (state.featureSwitchIsDebugging.data || state.featureSwitchIsTesting.data) {
if (state?.featureSwitchIsDebugging?.data || state?.featureSwitchIsTesting?.data) {
rendering = new Combine([
new FixedUiElement(configuration.id).SetClass("self-end subtle"),
rendering,
@ -55,7 +61,6 @@ export default class EditableTagRendering extends Toggle {
const self = this
editMode.addCallback((editing) => {
if (editing) {
console.log("Scrolling etr into view")
self.ScrollIntoView()
}
})
@ -66,13 +71,16 @@ export default class EditableTagRendering extends Toggle {
tags: UIEventSource<any>,
configuration: TagRenderingConfig,
units: Unit[],
editMode: UIEventSource<boolean>
editMode: UIEventSource<boolean>,
options?: {
saveButtonConstructor?: (src: Store<UploadableTag>) => BaseUIElement
}
): BaseUIElement {
const answer: BaseUIElement = new TagRenderingAnswer(tags, configuration, state)
answer.SetClass("w-full")
let rendering = answer
if (configuration.question !== undefined && state?.featureSwitchUserbadge?.data) {
if (configuration.question !== undefined && (state?.featureSwitchUserbadge?.data ?? true)) {
// We have a question and editing is enabled
const question = new Lazy(
@ -85,6 +93,7 @@ export default class EditableTagRendering extends Toggle {
.onClick(() => {
editMode.setData(false)
}),
saveButtonConstr: options?.saveButtonConstructor,
afterSave: () => {
editMode.setData(false)
},
@ -93,7 +102,7 @@ export default class EditableTagRendering extends Toggle {
const answerWithEditButton = new Combine([
answer,
new EditButton(state.osmConnection, () => {
new EditButton(state?.osmConnection, () => {
editMode.setData(true)
question.ScrollIntoView({
onlyIfPartiallyHidden: true,

View file

@ -48,7 +48,7 @@ export default class TagRenderingQuestion extends Combine {
afterSave?: () => void
cancelButton?: BaseUIElement
saveButtonConstr?: (src: Store<TagsFilter>) => BaseUIElement
bottomText?: (src: Store<TagsFilter>) => BaseUIElement
bottomText?: (src: Store<UploadableTag>) => BaseUIElement
}
) {
const applicableMappingsSrc = Stores.ListStabilized(
@ -100,28 +100,28 @@ export default class TagRenderingQuestion extends Combine {
})
)
const save = () => {
const selection = TagUtils.FlattenMultiAnswer(
TagUtils.FlattenAnd(inputElement.GetValue().data, tags.data)
)
if (selection) {
;(state?.changes)
.applyAction(
new ChangeTagAction(tags.data.id, selection, tags.data, {
theme: state?.layoutToUse?.id ?? "unkown",
changeType: "answer",
if (options.saveButtonConstr === undefined) {
const save = () => {
const selection = TagUtils.FlattenMultiAnswer(
TagUtils.FlattenAnd(inputElement.GetValue().data, tags.data)
)
if (selection) {
;(state?.changes)
.applyAction(
new ChangeTagAction(tags.data.id, selection, tags.data, {
theme: state?.layoutToUse?.id ?? "unkown",
changeType: "answer",
})
)
.then((_) => {
console.log("Tagchanges applied")
})
)
.then((_) => {
console.log("Tagchanges applied")
})
if (options.afterSave) {
options.afterSave()
if (options.afterSave) {
options.afterSave()
}
}
}
}
if (options.saveButtonConstr === undefined) {
options.saveButtonConstr = (v) => new SaveButton(v, state?.osmConnection).onClick(save)
}

View file

@ -263,4 +263,4 @@
"fr": "Une couche affichant les lieux où l'on peut nettoyer son vélo",
"cs": "Vrstva zobrazující zařízení, kde si můžete umýt kolo"
}
}
}

View file

@ -1493,6 +1493,39 @@
}
]
},
"picture-license": {
"description": "This question is not meant to be placed on an OpenStreetMap-element; however it is used in the user information panel to ask which license the user wants",
"question": {
"en": "Under what license do you want to publish your pictures?"
},
"mappings": [
{
"if": "mapcomplete-pictures-license=",
"then": {
"en": "No license has been chosen yet"
},
"hideInAnswer": true
},
{
"if": "mapcomplete-pictures-license=CC0",
"then": {
"en": "Pictures you take will be licensed with CC0 and added to the public domain. This means that everyone can use your pictures for any purpose."
}
},
{
"if": "mapcomplete-pictures-license=CC-BY 4.0",
"then": {
"en": "Pictures you take will be licensed with CC-BY 4.0 which requires everyone using your picture that they have to attribute you"
}
},
{
"if": "mapcomplete-pictures-license=CC-BY-SA 4.0",
"then": {
"en": "Pictures you take will be licensed with CC-BY-SA 4.0 which means that everyone using your picture must attribute you and that derivatives of your picture must be reshared with the same license."
}
}
]
},
"induction-loop": {
"description": "An accessibility feature: induction loops are for hard-hearing persons which have an FM-receiver.",
"question": {
@ -1766,4 +1799,4 @@
"ca": "El nom de la xarxa és <b>{internet_access:ssid}</b>"
}
}
}
}

View file

@ -791,6 +791,11 @@ video {
margin-bottom: 0.75rem;
}
.my-4 {
margin-top: 1rem;
margin-bottom: 1rem;
}
.mb-4 {
margin-bottom: 1rem;
}
@ -1092,11 +1097,6 @@ video {
width: 2.75rem;
}
.w-min {
width: -webkit-min-content;
width: min-content;
}
.w-max {
width: -webkit-max-content;
width: max-content;
@ -1106,6 +1106,11 @@ video {
width: 24rem;
}
.w-min {
width: -webkit-min-content;
width: min-content;
}
.w-auto {
width: auto;
}

View file

@ -261,12 +261,6 @@
},
"image": {
"addPicture": "Afegir foto",
"ccb": "sota la llicència CC-BY",
"ccbExplanation": "La llicència CC-BY implica que qualsevol persona pot utilitzar la teva imatge per a qualsevol propòsit, però t'ha d'atribuir",
"ccbs": "sota llicència CC-BY-SA",
"ccbsExplanation": "La llicència CC-BY-SA implica que qualsevol persona pot utilitzar la teva imatge per a qualsevol propòsit, però t'ha d'atribuir i les modificacions de la imatge s'han de tornar a publicar sota la mateixa llicència",
"cco": "en domini públic",
"ccoExplanation": "Afegir una imatge al domini públic implica que qualsevol pot fer qualsevol cosa amb la teva imatge",
"doDelete": "Esborrar imatge",
"dontDelete": "Cancel·lar",
"isDeleted": "Esborrada",
@ -280,8 +274,7 @@
"uploadFailed": "No s'ha pogut pujar la imatge. Tens Internet i es permeten API de tercers? El navegador Brave o UMatrix podria bloquejar-les.",
"uploadMultipleDone": "{count} imatges afegides. Gràcies per ajudar.",
"uploadingMultiple": "Pujant {count} imatges…",
"uploadingPicture": "Pujant la teva imatge…",
"willBePublished": "La teva foto serà publicada: "
"uploadingPicture": "Pujant la teva imatge…"
},
"importHelper": {
"introduction": {

View file

@ -275,12 +275,6 @@
},
"image": {
"addPicture": "Tilføj Billede",
"ccb": "under CC-BY-licensen",
"ccbExplanation": "The CC-BY licensen siger, at alle kan bruge dit billede til ethvert formål, men at de skal kreditere dig",
"ccbs": "under CC-BY-SA-licensen",
"ccbsExplanation": "CC-BY-SA licensen siger, at alle kan bruge dit billede til ethvert formål, men at de skal kreditere dig og at bearbejdelser af billedet skal offentliggøres under samme licens",
"cco": "i offentligt domæne",
"ccoExplanation": "At tilføje et billede til det offentlig domæne betyder, at alle kan gøre hvad som helst med dit billede",
"doDelete": "Fjern billede",
"dontDelete": "Afbryd",
"isDeleted": "Slettet",
@ -305,8 +299,7 @@
"uploadFailed": "Kunne ikke uploade dit billede. Er du forbundet til Internettet og tillader du tredieparts API'er. Brave browseren eller uMatrix plugin'et kunne blokerer dem.",
"uploadMultipleDone": "{count} billeder tilføjet. Tak for at hjælpe til!",
"uploadingMultiple": "Uploader {count} billeder…",
"uploadingPicture": "Uploading dit billede…",
"willBePublished": "Dit billede vil blive offentliggjort "
"uploadingPicture": "Uploading dit billede…"
},
"importHelper": {
"askMetadata": {

View file

@ -361,12 +361,6 @@
},
"image": {
"addPicture": "Bild hinzufügen",
"ccb": "unter der 'CC-BY-Lizenz'",
"ccbExplanation": "Die CC-BY-Lizenz besagt, dass jeder Ihr Bild für jeden Zweck verwenden darf, aber Sie müssen als Urheber genannt werden",
"ccbs": "unter der 'CC-BY-SA-Lizenz'",
"ccbsExplanation": "Die CC-BY-SA-Lizenz bedeutet, dass jeder Ihr Bild für jeden Zweck verwenden darf, aber Sie müssen genannt werden, und Remixe des Bildes müssen unter derselben Lizenz veröffentlicht werden",
"cco": "als 'Public Domain'",
"ccoExplanation": "Das Hinzufügen eines gemeinfreien Bildes impliziert, dass jeder alles mit Ihrem Bild machen kann",
"doDelete": "Bild entfernen",
"dontDelete": "Abbrechen",
"isDeleted": "Gelöscht",
@ -391,8 +385,7 @@
"uploadFailed": "Das Bild konnte nicht hochladen werden. Haben Sie eine aktive Internetverbindung und sind APIs von Dritten erlaubt? Der Brave Browser oder UMatrix blockieren diese eventuell.",
"uploadMultipleDone": "{count} Bilder wurden hinzugefügt. Vielen Dank für die Hilfe!",
"uploadingMultiple": "{count} Bilder hochladen…",
"uploadingPicture": "Bild wird hochgeladen…",
"willBePublished": "Ihr Bild wird veröffentlicht "
"uploadingPicture": "Bild wird hochgeladen…"
},
"importHelper": {
"askMetadata": {

View file

@ -365,12 +365,6 @@
},
"image": {
"addPicture": "Add picture",
"ccb": "under the CC-BY-license",
"ccbExplanation": "The CC-BY license implies that anyone may use your picture for any purpose, but they have to attribute you",
"ccbs": "under the CC-BY-SA-license",
"ccbsExplanation": "The CC-BY-SA license implies that anyone may use your picture for any purpose, but they have to attribute you and remixes of the picture have to be republished under the same license",
"cco": "in the public domain",
"ccoExplanation": "Adding a picture in the public domain implies that anyone can do anything with your picture",
"doDelete": "Remove image",
"dontDelete": "Cancel",
"isDeleted": "Deleted",
@ -395,8 +389,7 @@
"uploadFailed": "Could not upload your picture. Are you connected to the Internet, and allow third party API's? The Brave browser or the uMatrix plugin might block them.",
"uploadMultipleDone": "{count} pictures have been added. Thanks for helping out!",
"uploadingMultiple": "Uploading {count} pictures…",
"uploadingPicture": "Uploading your picture…",
"willBePublished": "Your picture will be published "
"uploadingPicture": "Uploading your picture…"
},
"importHelper": {
"askMetadata": {

View file

@ -95,15 +95,11 @@
},
"image": {
"addPicture": "Aldoni bildon",
"ccb": "laŭ la permesilo CC-BY",
"ccbs": "laŭ la permesilo CC-BY-SA",
"cco": "kiel publika havaĵo",
"dontDelete": "Nuligi",
"nearbyPictures": {},
"pleaseLogin": "Bonvolu saluti por aldoni bildon",
"uploadingMultiple": "Alŝutante {count} bildojn…",
"uploadingPicture": "Alŝutante vian bildon…",
"willBePublished": "Via bildo estos publikigita "
"uploadingPicture": "Alŝutante vian bildon…"
},
"importHelper": {
"askMetadata": {},

View file

@ -267,12 +267,6 @@
},
"image": {
"addPicture": "Añadir foto",
"ccb": "bajo licencia CC-BY",
"ccbExplanation": "La licencia CC-BY implica cualquiera podría utilizar tu fotografía para cualquier propósito, pero tienen que atribuirte",
"ccbs": "bajo licencia CC-BY-SA",
"ccbsExplanation": "La licencia CC-BY-SA implica que cualquier podría utilizar tu fotografía para cualquier propósito, pero tienen que atribuirte y los remixes de la fotografía tienen que ser publicados bajo la misma licencia",
"cco": "en dominio público",
"ccoExplanation": "Añadir una fotografía en el dominio público implica que cualquiera puede hacer cualquier cosa con tu fotografía",
"doDelete": "Borrar imagen",
"dontDelete": "Cancelar",
"isDeleted": "Borrada",
@ -297,8 +291,7 @@
"uploadFailed": "No se pudo cargar la imagen. ¿Tiene Internet y se permiten las API de terceros? El navegador Brave o uMatrix podría bloquearlas.",
"uploadMultipleDone": "Se han añadido {count} imágenes. Gracias por ayudar.",
"uploadingMultiple": "Cargando {count} imágenes…",
"uploadingPicture": "Cargando la imagen…",
"willBePublished": "La imagen se publicará "
"uploadingPicture": "Cargando la imagen…"
},
"importHelper": {
"askMetadata": {

View file

@ -67,8 +67,6 @@
},
"image": {
"addPicture": "Lisää kuva",
"ccb": "CC-BY-lisenssillä",
"ccbs": "CC-BY-SA-lisenssillä",
"doDelete": "Poista kuva",
"dontDelete": "Peruuta",
"isDeleted": "Poistettu",

View file

@ -302,10 +302,6 @@
},
"image": {
"addPicture": "Ajoutez une photo",
"ccb": "sous la license CC-BY",
"ccbExplanation": "La licence CC-BY implique que quiconque peut utiliser votre photo à n'importe quelle fin, mais qu'il doit vous citer.",
"ccbs": "sous la license CC-BY-SA",
"cco": "dans le domaine public",
"doDelete": "Supprimer l'image",
"dontDelete": "Annuler",
"isDeleted": "Supprimé",
@ -329,8 +325,7 @@
"uploadFailed": "L'ajout de la photo a échoué. Avez-vous accès à Internet ? Les API tierces sont-elles autorisées ? Le navigateur Brave ou UMatrix peuvent les bloquer.",
"uploadMultipleDone": "{count} images ont été ajoutées. Merci de votre contribution !",
"uploadingMultiple": "Mise en ligne de {count} photos…",
"uploadingPicture": "Mise en ligne de votre photo…",
"willBePublished": "Votre photo va être publiée : "
"uploadingPicture": "Mise en ligne de votre photo…"
},
"importHelper": {
"askMetadata": {

View file

@ -149,9 +149,6 @@
},
"image": {
"addPicture": "Engadir imaxe",
"ccb": "baixo a licenza CC-BY",
"ccbs": "baixo a licenza CC-BY-SA",
"cco": "no dominio público",
"doDelete": "Eliminar imaxe",
"dontDelete": "Cancelar",
"isDeleted": "Eliminada",
@ -161,8 +158,7 @@
"uploadDone": "<span class='thanks'>A túa imaxe foi engadida. Grazas por axudar.</span>",
"uploadFailed": "Non foi posíbel subir a imaxe. Tes internet e permites API de terceiros? O navegador Brave ou UMatrix podería bloquealas.",
"uploadingMultiple": "Subindo {count} das túas imaxes...",
"uploadingPicture": "Subindo a túa imaxe...",
"willBePublished": "A túa imaxe será publicada: "
"uploadingPicture": "Subindo a túa imaxe..."
},
"importHelper": {
"askMetadata": {},

View file

@ -256,12 +256,6 @@
},
"image": {
"addPicture": "Kép hozzáadása",
"ccb": "CC-BY licenc szerint",
"ccbExplanation": "A CC-BY licenc azt jelenti, hogy bárki bármilyen célra felhasználhatja a képet, de meg kell adnia a nevedet",
"ccbs": "CC-BY-SA licenc szerint",
"ccbsExplanation": "A CC-BY-SA licenc azt jelenti, hogy bárki bármilyen célra felhasználhatja a képet, de meg kell jelölnie Téged, a kép módosított változatait pedig ugyanezen licenc alatt kell újra közzétenni",
"cco": "közkincsként",
"ccoExplanation": "A kép közkinccsé tétele azt jelenti, hogy bárki bármit megtehet a képpel",
"doDelete": "Kép eltávolítása",
"dontDelete": "Mégse",
"isDeleted": "Törölve",
@ -273,8 +267,7 @@
"uploadFailed": "Nem sikerült feltölteni a képet. Van-e internetkapcsolatod, és engedélyezted-e a harmadik féltől származó API-kat? A Brave böngésző vagy a uMatrix bővítmény blokkolhatja őket.",
"uploadMultipleDone": "{count} kép hozzáadva. Köszönjük a segítséget!",
"uploadingMultiple": "{count} kép feltöltése folyamatban…",
"uploadingPicture": "Kép feltöltése folyamatban…",
"willBePublished": "A képed így lesz közzétéve: "
"uploadingPicture": "Kép feltöltése folyamatban…"
},
"importHelper": {
"askMetadata": {},

View file

@ -147,17 +147,13 @@
},
"image": {
"addPicture": "Tambahkan foto",
"ccb": "di bawah lisensi CC-BY",
"ccbs": "di bawah lisensi CC-BY-SA",
"cco": "di domain publik",
"doDelete": "Buang gambar",
"dontDelete": "Batal",
"isDeleted": "Dihapus",
"nearbyPictures": {},
"pleaseLogin": "Silakan masuk untuk menambah gambar",
"uploadingMultiple": "Mengunggah {count} gambar…",
"uploadingPicture": "Mengunggah gambar Anda…",
"willBePublished": "Gambarmu akan dipublikasikan "
"uploadingPicture": "Mengunggah gambar Anda…"
},
"importHelper": {
"askMetadata": {},

View file

@ -276,12 +276,6 @@
},
"image": {
"addPicture": "Aggiungi foto",
"ccb": "con licenza CC-BY",
"ccbExplanation": "La licenza CC-BY implica che autorizzi tutti ad usare la tua immagine per qualsiasi scopo, fintanto che i crediti a te sono corretti",
"ccbs": "con licenza CC-BY-SA",
"ccbsExplanation": "La licenza CC-BY-SA implica che autorizzi tutti ad usare la tua immagine per qualsiasi scopo, fintanto che i crediti a te sono corretti e le modifiche a questa immagine sono pubblicate con la medesima licenza",
"cco": "nel pubblico dominio",
"ccoExplanation": "Aggiungere una immagine nel pubblico dominio implica che autorizzi tutti a fare qualsiasi cosa con questa immagine",
"doDelete": "Rimuovi immagine",
"dontDelete": "Annulla",
"isDeleted": "Cancellata",
@ -306,8 +300,7 @@
"uploadFailed": "Impossibile caricare la tua foto. La connessione internet è attiva e le API di terze parti sono abilitate? Il browser Brave o il plugin uMatrix potrebbero bloccarle.",
"uploadMultipleDone": "Sono state aggiunte {count} immagini. Grazie per laiuto!",
"uploadingMultiple": "Caricamento di {count} foto…",
"uploadingPicture": "Caricamento della tua foto…",
"willBePublished": "La tua foto sarà pubblicata: "
"uploadingPicture": "Caricamento della tua foto…"
},
"importHelper": {
"askMetadata": {

View file

@ -150,9 +150,6 @@
},
"image": {
"addPicture": "写真の追加",
"ccb": "CC-BY-ライセンスで",
"ccbs": "CC-BY-SA-ライセンスで",
"cco": "パブリックドメインで",
"doDelete": "イメージの削除",
"dontDelete": "[キャンセル]",
"isDeleted": "削除済み",
@ -162,8 +159,7 @@
"uploadDone": "<span class=\"thanks\">あなたの写真が追加されました。ご協力ありがとうございます!</span>",
"uploadFailed": "写真をアップロードできませんでした。インターネット接続があり、外部のAPIが許可されていますかBrave ブラウザやUMatrixは、これらをブロックするかもしれません。",
"uploadingMultiple": "{count} 枚の写真をアップロードします…",
"uploadingPicture": "写真をアップロードします…",
"willBePublished": "写真は公開されます: "
"uploadingPicture": "写真をアップロードします…"
},
"importHelper": {
"askMetadata": {},

View file

@ -286,8 +286,6 @@
},
"image": {
"addPicture": "Legg til bilde",
"ccb": "med CC-BY-lisens",
"ccbs": "med CC-BY-SA-lisens",
"doDelete": "Fjern bilde",
"dontDelete": "Avbryt",
"isDeleted": "Slettet",
@ -306,8 +304,7 @@
"uploadFailed": "Kunne ikke laste opp bildet ditt. Er du tilkoblet Internett og tillater tredjeparts-API-er? Brave-nettleseren eller uMatrix-programtillegget kan blokkere dem.",
"uploadMultipleDone": "{count} bilder har blitt lagt til. Takk for at du hjelper til.",
"uploadingMultiple": "Laster opp {count} bilder …",
"uploadingPicture": "Laster opp bildet ditt …",
"willBePublished": "Ditt bilde vil bli publisert: "
"uploadingPicture": "Laster opp bildet ditt …"
},
"importHelper": {
"askMetadata": {

View file

@ -361,12 +361,6 @@
},
"image": {
"addPicture": "Voeg foto toe",
"ccb": "onder de CC-BY-licentie",
"ccbExplanation": "Als je foto met de CC-BY-SA-licentie gepubliceerd wordt, dan mag je foto gebruikt worden voor alle doeleinden, maar je naam moet vermeld worden",
"ccbs": "onder de CC-BY-SA-licentie",
"ccbsExplanation": "Als je foto met de CC-BY-SA-licentie gepubliceerd wordt, dan mag je foto gebruikt worden voor alle doeleinden, maar je naam moet vermeld worden en afgeleide werken moeten onder dezelfde licentie gepubliceerd worden",
"cco": "in het publiek domein",
"ccoExplanation": "Als je foto in het publiek domein gepubliceerd wordt, dan mag iedereen je foto voor alle doeleinden gebruiken",
"doDelete": "Verwijder afbeelding",
"dontDelete": "Annuleren",
"isDeleted": "Verwijderd",
@ -391,8 +385,7 @@
"uploadFailed": "Afbeelding uploaden mislukt. Heb je internet? Gebruik je Brave of UMatrix? Dan moet je derde partijen toelaten.",
"uploadMultipleDone": "{count} afbeeldingen zijn toegevoegd. Bedankt voor je bijdrage!",
"uploadingMultiple": "Bezig met {count} foto's te uploaden…",
"uploadingPicture": "Bezig met een foto te uploaden…",
"willBePublished": "Jouw foto wordt gepubliceerd "
"uploadingPicture": "Bezig met een foto te uploaden…"
},
"importHelper": {
"askMetadata": {

View file

@ -142,10 +142,6 @@
},
"image": {
"addPicture": "Dodaj zdjęcie",
"ccb": "na licencji CC-BY",
"ccbs": "na licencji CC-BY-SA",
"cco": "w domenie publicznej",
"ccoExplanation": "Dodanie zdjęcia do domeny publicznej oznacza, że każdy może zrobić z nim cokolwiek zechce",
"doDelete": "Usuń ilustrację",
"dontDelete": "Anuluj",
"isDeleted": "Usunięte",
@ -157,8 +153,7 @@
"uploadDone": "Twoje zdjęcie zostało dodane. Dzięki za pomoc!",
"uploadFailed": "Wysyłanie zdjęcia nie powiodło się. Czy masz połączenie z internetem i włączony dostęp zewnętrznych API? Przeglądarki Brave i UMatrix mogą je blokować.",
"uploadingMultiple": "Wysyłanie {count} zdjęć…",
"uploadingPicture": "Wysyłanie zdjęcia…",
"willBePublished": "Twoje zdjęcie zostanie opublikowane "
"uploadingPicture": "Wysyłanie zdjęcia…"
},
"index": {
"#": "Te teksty są wyświetlane nad przyciskami motywu, gdy nie jest załadowany żaden motyw",

View file

@ -276,12 +276,6 @@
},
"image": {
"addPicture": "Adicionar imagem",
"ccb": "sob a licença CC-BY",
"ccbExplanation": "A licença CC-BY implica que qualquer pessoa pode usar sua fotografia para qualquer finalidade, mas têm de atribuir a autoria a si",
"ccbs": "sob a licença CC-BY-SA",
"ccbsExplanation": "A licença CC-BY-SA implica que qualquer pessoa pode usar sua imagem para qualquer finalidade, mas têm de atribuir a autoria a si e remixes da imagem devem ser republicados sob a mesma licença",
"cco": "no domínio público",
"ccoExplanation": "Adicionar uma fotografia no domínio público implica que qualquer pessoa pode fazer qualquer coisa com a sua fotografia",
"doDelete": "Remover imagem",
"dontDelete": "Cancelar",
"isDeleted": "Eliminada",
@ -306,8 +300,7 @@
"uploadFailed": "Não foi possível enviar a sua imagem. Está conectado à Internet e permite APIs de terceiros? O navegador \"Brave\" ou o plugin \"uMatrix\" podem estar a bloqueá-los.",
"uploadMultipleDone": "Foram adicionadas {count} fotografias. Obrigado por ajudar!",
"uploadingMultiple": "A enviar {count} imagens…",
"uploadingPicture": "A enviar a sua imagem…",
"willBePublished": "A sua imagem será publicada: "
"uploadingPicture": "A enviar a sua imagem…"
},
"importHelper": {
"askMetadata": {

View file

@ -130,9 +130,6 @@
},
"image": {
"addPicture": "Adicionar imagem",
"ccb": "sob a licença CC-BY",
"ccbs": "sob a licença CC-BY-SA",
"cco": "no domínio público",
"doDelete": "Remover imagem",
"dontDelete": "Cancelar",
"isDeleted": "Excluída",
@ -141,8 +138,7 @@
"uploadDone": "<span class=\"thanks\">Sua foto foi adicionada. Obrigado por ajudar!</span>",
"uploadFailed": "Não foi possível enviar sua foto. Você está conectado à Internet e permite APIs de terceiros? O navegador Brave ou o plugin uMatrix podem bloqueá-los.",
"uploadingMultiple": "Fazendo upload de {count} imagens…",
"uploadingPicture": "Enviando sua imagem…",
"willBePublished": "Sua imagem será publicada: "
"uploadingPicture": "Enviando sua imagem…"
},
"index": {
"#": "Estes textos são mostrados acima dos botões do tema quando nenhum tema é carregado",

View file

@ -156,9 +156,6 @@
},
"image": {
"addPicture": "Добавить изображение",
"ccb": "под лицензией CC-BY",
"ccbs": "под лицензией CC-BY-SA",
"cco": "в открытом доступе",
"doDelete": "Удалить изображение",
"dontDelete": "Отмена",
"isDeleted": "Удалено",
@ -169,8 +166,7 @@
"uploadFailed": "Не удалось загрузить изображение. Проверьте, есть ли у вас доступ в Интернет и разрешены ли сторонние API? Браузеры Brave и UMatrix могут блокировать их.",
"uploadMultipleDone": "{count} изображений добавлено. Спасибо за помощь!",
"uploadingMultiple": "Загружаем {count} изображений…",
"uploadingPicture": "Загружаем изображение…",
"willBePublished": "Ваше изображение будет опубликовано "
"uploadingPicture": "Загружаем изображение…"
},
"importHelper": {
"askMetadata": {},

View file

@ -66,9 +66,6 @@
},
"image": {
"addPicture": "Lägg till bild",
"ccb": "under CC-BY-licensen",
"ccbs": "under CC-BY-SA-licensen",
"cco": "med fri användning (public domain)",
"doDelete": "Ta bort bild",
"dontDelete": "Avbryt",
"isDeleted": "Borttagen",
@ -80,8 +77,7 @@
"uploadFailed": "Misslyckades med att ladda upp din bild. Är du säker på att du är uppkopplad och tredjeparts-API:er tillåts? Brave eller uMatrix kanske blockerar dem.",
"uploadMultipleDone": "{count} bilder har lagts till. Tack för att du hjälper till!",
"uploadingMultiple": "Laddar upp {count} bilder…",
"uploadingPicture": "Laddar upp din bild…",
"willBePublished": "Din bild kommer att publiceras: "
"uploadingPicture": "Laddar upp din bild…"
},
"importHelper": {
"askMetadata": {},

View file

@ -799,6 +799,13 @@
"question": "Made with host {search}"
}
}
},
"7": {
"options": {
"0": {
"question": "Changeset added at least one image"
}
}
}
},
"name": "Changeset centers",

View file

@ -282,12 +282,6 @@
},
"image": {
"addPicture": "新增圖片",
"ccb": "以 CC-BY 授權條款",
"ccbExplanation": "創用CC性名標示意味著任何人可以居於任何目標使用你的圖片但必須署名作者為你",
"ccbs": "以 CC-BY-SA 授權條款",
"ccbsExplanation": "創用CC姓名標示相同方式分享授權意味著任何人能居於任何目的都能使用你的圖片但必須標示你為作者如果會混搭運用圖片的話圖片的再釋出也必須遵循相同的授權條款",
"cco": "公有領域",
"ccoExplanation": "將圖片以公眾領域釋出,意味著任何人能夠運用你的圖片做任何事情",
"doDelete": "移除圖片",
"dontDelete": "取消",
"isDeleted": "已移除",
@ -312,8 +306,7 @@
"uploadFailed": "無法上傳您的圖片。您是否已連線至網際網路,並允許第三方 APIBrave 瀏覽器或 uMatrix 外掛程式都可能會封鎖它們。",
"uploadMultipleDone": "已經新增 {count} 圖片,謝謝你的幫忙!",
"uploadingMultiple": "正在上傳 {count} 張圖片…",
"uploadingPicture": "正在上傳你的圖片…",
"willBePublished": "你的圖片將依以下授權釋出: "
"uploadingPicture": "正在上傳你的圖片…"
},
"importHelper": {
"askMetadata": {

View file

@ -4,7 +4,9 @@ import * as fs from "fs"
async function main(args: string[]) {
if (args.length !== 1) {
console.log("Usage: first argument is the fully qualified key of the string to remove")
console.log(
"Usage: first argument is the fully qualified key of the string to remove. Only removes translations in the core translations"
)
return
}
const path = args[0].split(".")