forked from MapComplete/MapComplete
Merge develop
This commit is contained in:
commit
ccf9c4b5f6
50 changed files with 1427 additions and 766 deletions
|
@ -14,7 +14,7 @@ export default class AddNewMarker extends Combine {
|
|||
let last = undefined;
|
||||
for (const filteredLayer of filteredLayers) {
|
||||
const layer = filteredLayer.layerDef;
|
||||
if(layer.name === undefined){
|
||||
if(layer.name === undefined && !filteredLayer.isDisplayed.data){
|
||||
continue
|
||||
}
|
||||
for (const preset of filteredLayer.layerDef.presets) {
|
||||
|
|
|
@ -22,7 +22,7 @@ import {OsmConnection} from "../../Logic/Osm/OsmConnection";
|
|||
import Constants from "../../Models/Constants";
|
||||
import ContributorCount from "../../Logic/ContributorCount";
|
||||
import Img from "../Base/Img";
|
||||
import {Translation} from "../i18n/Translation";
|
||||
import {TypedTranslation} from "../i18n/Translation";
|
||||
import TranslatorsPanel from "./TranslatorsPanel";
|
||||
|
||||
export class OpenIdEditor extends VariableUiElement {
|
||||
|
@ -198,7 +198,7 @@ export default class CopyrightPanel extends Combine {
|
|||
this.SetStyle("max-width:100%; width: 40rem; margin-left: 0.75rem; margin-right: 0.5rem")
|
||||
}
|
||||
|
||||
private static CodeContributors(contributors, translation: Translation): BaseUIElement {
|
||||
private static CodeContributors(contributors, translation: TypedTranslation<{contributors, hiddenCount}>): BaseUIElement {
|
||||
|
||||
const total = contributors.contributors.length;
|
||||
let filtered = [...contributors.contributors]
|
||||
|
|
|
@ -90,10 +90,10 @@ export default class MoreScreen extends Combine {
|
|||
}
|
||||
|
||||
let hash = ""
|
||||
if(layout.definition !== undefined){
|
||||
hash = "#"+btoa(JSON.stringify(layout.definition))
|
||||
if (layout.definition !== undefined) {
|
||||
hash = "#" + btoa(JSON.stringify(layout.definition))
|
||||
}
|
||||
|
||||
|
||||
const linkText = currentLocation?.map(currentLocation => {
|
||||
const params = [
|
||||
["z", currentLocation?.zoom],
|
||||
|
@ -106,11 +106,10 @@ export default class MoreScreen extends Combine {
|
|||
}) ?? new UIEventSource<string>(`${linkPrefix}`)
|
||||
|
||||
|
||||
|
||||
return new SubtleButton(layout.icon,
|
||||
new Combine([
|
||||
`<dt class='text-lg leading-6 font-medium text-gray-900 group-hover:text-blue-800'>`,
|
||||
new Translation(layout.title, !isCustom && !layout.mustHaveLanguage ? "themes:"+layout.id+".title" : undefined),
|
||||
new Translation(layout.title, !isCustom && !layout.mustHaveLanguage ? "themes:" + layout.id + ".title" : undefined),
|
||||
`</dt>`,
|
||||
`<dd class='mt-1 text-base text-gray-500 group-hover:text-blue-900 overflow-ellipsis'>`,
|
||||
new Translation(layout.shortDescription)?.SetClass("subtle") ?? "",
|
||||
|
@ -128,15 +127,13 @@ export default class MoreScreen extends Combine {
|
|||
}
|
||||
|
||||
private static createUnofficialButtonFor(state: UserRelatedState, id: string): BaseUIElement {
|
||||
const allPreferences = state.osmConnection.preferencesHandler.preferences.data;
|
||||
const length = Number(allPreferences[id + "-length"])
|
||||
let str = "";
|
||||
for (let i = 0; i < length; i++) {
|
||||
str += allPreferences[id + "-" + i]
|
||||
}
|
||||
if(str === undefined || str === "undefined"){
|
||||
const pref = state.osmConnection.GetLongPreference(id)
|
||||
const str = pref.data
|
||||
if (str === undefined || str === "undefined" || str === "") {
|
||||
pref.setData(null)
|
||||
return undefined
|
||||
}
|
||||
|
||||
try {
|
||||
const value: {
|
||||
id: string
|
||||
|
@ -149,7 +146,8 @@ export default class MoreScreen extends Combine {
|
|||
value.isOfficial = false
|
||||
return MoreScreen.createLinkButton(state, value, true)
|
||||
} catch (e) {
|
||||
console.debug("Could not parse unofficial theme information for " + id, "The json is: ", str, e)
|
||||
console.warn("Removing theme " + id + " as it could not be parsed from the preferences")
|
||||
pref.setData(null)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
@ -163,16 +161,14 @@ export default class MoreScreen extends Combine {
|
|||
|
||||
for (const key in allPreferences) {
|
||||
if (key.startsWith(prefix) && key.endsWith("-combined-length")) {
|
||||
const id = key.substring(0, key.length - "-length".length)
|
||||
const id = key.substring("mapcomplete-".length, key.length - "-combined-length".length)
|
||||
ids.push(id)
|
||||
}
|
||||
}
|
||||
|
||||
return ids
|
||||
});
|
||||
|
||||
var stableIds = UIEventSource.ListStabilized<string>(currentIds)
|
||||
|
||||
return new VariableUiElement(
|
||||
stableIds.map(ids => {
|
||||
const allThemes: BaseUIElement[] = []
|
||||
|
@ -182,12 +178,11 @@ export default class MoreScreen extends Combine {
|
|||
allThemes.push(link.SetClass(buttonClass))
|
||||
}
|
||||
}
|
||||
|
||||
if (allThemes.length <= 0) {
|
||||
return undefined;
|
||||
}
|
||||
return new Combine([
|
||||
Translations.t.general.customThemeIntro.Clone(),
|
||||
Translations.t.general.customThemeIntro,
|
||||
new Combine(allThemes).SetClass(themeListClasses)
|
||||
]);
|
||||
}));
|
||||
|
|
|
@ -208,15 +208,20 @@ export default class SimpleAddUI extends Toggle {
|
|||
const allButtons = [];
|
||||
for (const layer of state.filteredLayers.data) {
|
||||
|
||||
if (layer.isDisplayed.data === false && !state.featureSwitchFilter.data) {
|
||||
// The layer is not displayed and we cannot enable the layer control -> we skip
|
||||
continue;
|
||||
if (layer.isDisplayed.data === false) {
|
||||
// The layer is not displayed...
|
||||
if(!state.featureSwitchFilter.data){
|
||||
// ...and we cannot enable the layer control -> we skip, as these presets can never be shown anyway
|
||||
continue;
|
||||
}
|
||||
|
||||
if (layer.layerDef.name === undefined) {
|
||||
// this layer can never be toggled on in any case, so we skip the presets
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (layer.layerDef.name === undefined) {
|
||||
// this is a parlty hidden layer
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const presets = layer.layerDef.presets;
|
||||
for (const preset of presets) {
|
||||
|
|
|
@ -14,7 +14,9 @@ import Title from "../Base/Title";
|
|||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {SubtleButton} from "../Base/SubtleButton";
|
||||
import Svg from "../../Svg";
|
||||
|
||||
import * as native_languages from "../../assets/language_native.json"
|
||||
import * as used_languages from "../../assets/generated/used_languages.json"
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
|
||||
class TranslatorsPanelContent extends Combine {
|
||||
constructor(layout: LayoutConfig, isTranslator: UIEventSource<boolean>) {
|
||||
|
@ -24,36 +26,53 @@ class TranslatorsPanelContent extends Combine {
|
|||
|
||||
const seed = t.completeness
|
||||
for (const ln of Array.from(completeness.keys())) {
|
||||
if(ln === "*"){
|
||||
if (ln === "*") {
|
||||
continue
|
||||
}
|
||||
if (seed.translations[ln] === undefined) {
|
||||
seed.translations[ln] = seed.translations["en"]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const completenessTr = {}
|
||||
const completenessPercentage = {}
|
||||
seed.SupportedLanguages().forEach(ln => {
|
||||
completenessTr[ln] = ""+(completeness.get(ln) ?? 0)
|
||||
completenessPercentage[ln] = ""+Math.round(100 * (completeness.get(ln) ?? 0) / total)
|
||||
completenessTr[ln] = "" + (completeness.get(ln) ?? 0)
|
||||
completenessPercentage[ln] = "" + Math.round(100 * (completeness.get(ln) ?? 0) / total)
|
||||
})
|
||||
|
||||
const missingTranslationsFor = (ln: string) => Utils.NoNull(untranslated.get(ln) ?? [])
|
||||
.filter(ctx => ctx.indexOf(":") >= 0)
|
||||
.map(ctx => ctx.replace(/note_import_[a-zA-Z0-9_]*/, "note_import"))
|
||||
.map(context => new Link(context, LinkToWeblate.hrefToWeblate(ln, context), true))
|
||||
function missingTranslationsFor(language: string): BaseUIElement[] {
|
||||
// e.g. "themes:<themename>.layers.0.tagRenderings..., or "layers:<layername>.description
|
||||
const missingKeys = Utils.NoNull(untranslated.get(language) ?? [])
|
||||
.filter(ctx => ctx.indexOf(":") >= 0)
|
||||
.map(ctx => ctx.replace(/note_import_[a-zA-Z0-9_]*/, "note_import"))
|
||||
|
||||
const hasMissingTheme = missingKeys.some(k => k.startsWith("themes:"))
|
||||
const missingLayers = Utils.Dedup( missingKeys.filter(k => k.startsWith("layers:"))
|
||||
.map(k => k.slice("layers:".length).split(".")[0]))
|
||||
|
||||
console.log("Getting untranslated string for",language,"raw:",missingKeys,"hasMissingTheme:",hasMissingTheme,"missingLayers:",missingLayers)
|
||||
return [
|
||||
hasMissingTheme ? new Link("themes:" + layout.id + ".* (zen mode)", LinkToWeblate.hrefToWeblateZen(language, "themes", layout.id), true) : undefined,
|
||||
...missingLayers.map(id => new Link("layer:" + id + ".* (zen mode)", LinkToWeblate.hrefToWeblateZen(language, "layers", id), true)),
|
||||
...missingKeys.map(context => new Link(context, LinkToWeblate.hrefToWeblate(language, context), true))
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// "translationCompleteness": "Translations for {theme} in {language} are at {percentage}: {translated} out of {total}",
|
||||
const translated = seed.Subs({total, theme: layout.title,
|
||||
const translated = seed.Subs({
|
||||
total, theme: layout.title,
|
||||
percentage: new Translation(completenessPercentage),
|
||||
translated: new Translation(completenessTr)
|
||||
translated: new Translation(completenessTr),
|
||||
language: seed.OnEveryLanguage((_, lng) => native_languages[lng] ?? lng)
|
||||
})
|
||||
|
||||
|
||||
super([
|
||||
new Title(
|
||||
Translations.t.translations.activateButton,
|
||||
Translations.t.translations.activateButton,
|
||||
),
|
||||
new Toggle(t.isTranslator.SetClass("thanks block"), undefined, isTranslator),
|
||||
t.help,
|
||||
|
@ -63,15 +82,18 @@ class TranslatorsPanelContent extends Combine {
|
|||
.onClick(() => {
|
||||
Locale.showLinkToWeblate.setData(false)
|
||||
}),
|
||||
|
||||
new VariableUiElement(Locale.language.map(ln => {
|
||||
|
||||
new VariableUiElement(Locale.language.map(ln => {
|
||||
const missing = missingTranslationsFor(ln)
|
||||
if (missing.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
let title = Translations.t.translations.allMissing;
|
||||
if(untranslated.get(ln) !== undefined){
|
||||
title = Translations.t.translations.missing.Subs({count: untranslated.get(ln).length})
|
||||
}
|
||||
return new Toggleable(
|
||||
new Title(Translations.t.translations.missing.Subs({count: missing.length})),
|
||||
new Title(title),
|
||||
new Combine(missing).SetClass("flex flex-col")
|
||||
)
|
||||
}))
|
||||
|
@ -83,38 +105,37 @@ class TranslatorsPanelContent extends Combine {
|
|||
|
||||
export default class TranslatorsPanel extends Toggle {
|
||||
|
||||
|
||||
|
||||
constructor(state: { layoutToUse: LayoutConfig, isTranslator: UIEventSource<boolean> }, iconStyle?: string) {
|
||||
const t = Translations.t.translations
|
||||
super(
|
||||
new Lazy(() => new TranslatorsPanelContent(state.layoutToUse, state.isTranslator)
|
||||
new Lazy(() => new TranslatorsPanelContent(state.layoutToUse, state.isTranslator)
|
||||
).SetClass("flex flex-col"),
|
||||
new SubtleButton(Svg.translate_ui().SetStyle(iconStyle), t.activateButton).onClick(() => Locale.showLinkToWeblate.setData(true)),
|
||||
Locale.showLinkToWeblate
|
||||
Locale.showLinkToWeblate
|
||||
)
|
||||
this.SetClass("hidden-on-mobile")
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static MissingTranslationsFor(layout: LayoutConfig) : {completeness: Map<string, number>, untranslated: Map<string, string[]>, total: number} {
|
||||
public static MissingTranslationsFor(layout: LayoutConfig): { completeness: Map<string, number>, untranslated: Map<string, string[]>, total: number } {
|
||||
let total = 0
|
||||
const completeness = new Map<string, number>()
|
||||
const untranslated = new Map<string, string[]>()
|
||||
|
||||
Utils.WalkObject(layout, (o, path) => {
|
||||
const translation = <Translation><any>o;
|
||||
if(translation.translations["*"] !== undefined){
|
||||
if (translation.translations["*"] !== undefined) {
|
||||
return
|
||||
}
|
||||
if(translation.context === undefined || translation.context.indexOf(":") < 0){
|
||||
if (translation.context === undefined || translation.context.indexOf(":") < 0) {
|
||||
// no source given - lets ignore
|
||||
return
|
||||
}
|
||||
|
||||
for (const lang of translation.SupportedLanguages()) {
|
||||
completeness.set(lang, 1 + (completeness.get(lang) ?? 0))
|
||||
}
|
||||
layout.title.SupportedLanguages().forEach(ln => {
|
||||
|
||||
total ++
|
||||
used_languages.languages.forEach(ln => {
|
||||
const trans = translation.translations
|
||||
if (trans["*"] !== undefined) {
|
||||
return;
|
||||
|
@ -124,11 +145,11 @@ export default class TranslatorsPanel extends Toggle {
|
|||
untranslated.set(ln, [])
|
||||
}
|
||||
untranslated.get(ln).push(translation.context)
|
||||
}else{
|
||||
completeness.set(ln, 1 + (completeness.get(ln) ?? 0))
|
||||
}
|
||||
})
|
||||
if(translation.translations["*"] === undefined){
|
||||
total++
|
||||
}
|
||||
|
||||
}, o => {
|
||||
if (o === undefined || o === null) {
|
||||
return false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue