forked from MapComplete/MapComplete
Add typings to translations, move Subs into 'TypedTranslations', cleanup of duplicate parts in translation files, fix #752
This commit is contained in:
parent
f5d5f304ae
commit
e391c1ce20
12 changed files with 64 additions and 318 deletions
|
@ -1,4 +1,4 @@
|
||||||
import {Translation} from "../../UI/i18n/Translation";
|
import {Translation, TypedTranslation} from "../../UI/i18n/Translation";
|
||||||
import {TagsFilter} from "../../Logic/Tags/TagsFilter";
|
import {TagsFilter} from "../../Logic/Tags/TagsFilter";
|
||||||
import Translations from "../../UI/i18n/Translations";
|
import Translations from "../../UI/i18n/Translations";
|
||||||
import {TagUtils} from "../../Logic/Tags/TagUtils";
|
import {TagUtils} from "../../Logic/Tags/TagUtils";
|
||||||
|
@ -22,8 +22,8 @@ export default class TagRenderingConfig {
|
||||||
|
|
||||||
public readonly id: string;
|
public readonly id: string;
|
||||||
public readonly group: string;
|
public readonly group: string;
|
||||||
public readonly render?: Translation;
|
public readonly render?: TypedTranslation<object>;
|
||||||
public readonly question?: Translation;
|
public readonly question?: TypedTranslation<object>;
|
||||||
public readonly condition?: TagsFilter;
|
public readonly condition?: TagsFilter;
|
||||||
|
|
||||||
public readonly configuration_warnings: string[] = []
|
public readonly configuration_warnings: string[] = []
|
||||||
|
@ -43,7 +43,7 @@ export default class TagRenderingConfig {
|
||||||
public readonly mappings?: {
|
public readonly mappings?: {
|
||||||
readonly if: TagsFilter,
|
readonly if: TagsFilter,
|
||||||
readonly ifnot?: TagsFilter,
|
readonly ifnot?: TagsFilter,
|
||||||
readonly then: Translation,
|
readonly then: TypedTranslation<object>,
|
||||||
readonly icon: string,
|
readonly icon: string,
|
||||||
readonly iconClass: string
|
readonly iconClass: string
|
||||||
readonly hideInAnswer: boolean | TagsFilter
|
readonly hideInAnswer: boolean | TagsFilter
|
||||||
|
@ -110,12 +110,13 @@ export default class TagRenderingConfig {
|
||||||
}
|
}
|
||||||
const type = json.freeform.type ?? "string"
|
const type = json.freeform.type ?? "string"
|
||||||
|
|
||||||
let placeholder = Translations.T(json.freeform.placeholder)
|
let placeholder: Translation = Translations.T(json.freeform.placeholder)
|
||||||
if (placeholder === undefined) {
|
if (placeholder === undefined) {
|
||||||
const typeDescription = Translations.t.validation[type]?.description
|
const typeDescription = Translations.t.validation[type]?.description
|
||||||
placeholder = Translations.T(json.freeform.key+" ("+type+")")
|
|
||||||
if(typeDescription !== undefined){
|
if(typeDescription !== undefined){
|
||||||
placeholder = placeholder.Subs({[type]: typeDescription})
|
placeholder = Translations.T(json.freeform.key+" ("+type+")").Subs({[type]: typeDescription})
|
||||||
|
}else{
|
||||||
|
placeholder = Translations.T(json.freeform.key+" ("+type+")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,7 +384,7 @@ export default class TagRenderingConfig {
|
||||||
let freeformKeyDefined = this.freeform?.key !== undefined;
|
let freeformKeyDefined = this.freeform?.key !== undefined;
|
||||||
let usedFreeformValues = new Set<string>()
|
let usedFreeformValues = new Set<string>()
|
||||||
// We run over all the mappings first, to check if the mapping matches
|
// We run over all the mappings first, to check if the mapping matches
|
||||||
const applicableMappings: { then: Translation, img?: string }[] = Utils.NoNull((this.mappings ?? [])?.map(mapping => {
|
const applicableMappings: { then: TypedTranslation<any>, img?: string }[] = Utils.NoNull((this.mappings ?? [])?.map(mapping => {
|
||||||
if (mapping.if === undefined) {
|
if (mapping.if === undefined) {
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
@ -404,7 +405,7 @@ export default class TagRenderingConfig {
|
||||||
const leftovers = freeformValues.filter(v => !usedFreeformValues.has(v))
|
const leftovers = freeformValues.filter(v => !usedFreeformValues.has(v))
|
||||||
for (const leftover of leftovers) {
|
for (const leftover of leftovers) {
|
||||||
applicableMappings.push({then:
|
applicableMappings.push({then:
|
||||||
this.render.replace("{"+this.freeform.key+"}", leftover)
|
new TypedTranslation<object>(this.render.replace("{"+this.freeform.key+"}", leftover).translations)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,7 +413,7 @@ export default class TagRenderingConfig {
|
||||||
return applicableMappings
|
return applicableMappings
|
||||||
}
|
}
|
||||||
|
|
||||||
public GetRenderValue(tags: any, defltValue: any = undefined): Translation {
|
public GetRenderValue(tags: any, defltValue: any = undefined): TypedTranslation<any> {
|
||||||
return this.GetRenderValueWithImage(tags, defltValue).then
|
return this.GetRenderValueWithImage(tags, defltValue).then
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,7 +422,7 @@ export default class TagRenderingConfig {
|
||||||
* Not compatible with multiAnswer - use GetRenderValueS instead in that case
|
* Not compatible with multiAnswer - use GetRenderValueS instead in that case
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
public GetRenderValueWithImage(tags: any, defltValue: any = undefined): { then: Translation, icon?: string } {
|
public GetRenderValueWithImage(tags: any, defltValue: any = undefined): { then: TypedTranslation<any>, icon?: string } {
|
||||||
if (this.mappings !== undefined && !this.multiAnswer) {
|
if (this.mappings !== undefined && !this.multiAnswer) {
|
||||||
for (const mapping of this.mappings) {
|
for (const mapping of this.mappings) {
|
||||||
if (mapping.if === undefined) {
|
if (mapping.if === undefined) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import {OsmConnection} from "../../Logic/Osm/OsmConnection";
|
||||||
import Constants from "../../Models/Constants";
|
import Constants from "../../Models/Constants";
|
||||||
import ContributorCount from "../../Logic/ContributorCount";
|
import ContributorCount from "../../Logic/ContributorCount";
|
||||||
import Img from "../Base/Img";
|
import Img from "../Base/Img";
|
||||||
import {Translation} from "../i18n/Translation";
|
import {TypedTranslation} from "../i18n/Translation";
|
||||||
import TranslatorsPanel from "./TranslatorsPanel";
|
import TranslatorsPanel from "./TranslatorsPanel";
|
||||||
|
|
||||||
export class OpenIdEditor extends VariableUiElement {
|
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")
|
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;
|
const total = contributors.contributors.length;
|
||||||
let filtered = [...contributors.contributors]
|
let filtered = [...contributors.contributors]
|
||||||
|
|
|
@ -14,7 +14,7 @@ import Title from "../Base/Title";
|
||||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||||
import {SubtleButton} from "../Base/SubtleButton";
|
import {SubtleButton} from "../Base/SubtleButton";
|
||||||
import Svg from "../../Svg";
|
import Svg from "../../Svg";
|
||||||
|
import * as native_languages from "../../assets/language_native.json"
|
||||||
|
|
||||||
class TranslatorsPanelContent extends Combine {
|
class TranslatorsPanelContent extends Combine {
|
||||||
constructor(layout: LayoutConfig, isTranslator: UIEventSource<boolean>) {
|
constructor(layout: LayoutConfig, isTranslator: UIEventSource<boolean>) {
|
||||||
|
@ -48,7 +48,8 @@ class TranslatorsPanelContent extends Combine {
|
||||||
// "translationCompleteness": "Translations for {theme} in {language} are at {percentage}: {translated} out of {total}",
|
// "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),
|
percentage: new Translation(completenessPercentage),
|
||||||
translated: new Translation(completenessTr)
|
translated: new Translation(completenessTr),
|
||||||
|
language: seed.OnEveryLanguage((_, lng) => native_languages[lng])
|
||||||
})
|
})
|
||||||
|
|
||||||
super([
|
super([
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default class ReviewElement extends VariableUiElement {
|
||||||
SingleReview.GenStars(avg),
|
SingleReview.GenStars(avg),
|
||||||
new Link(
|
new Link(
|
||||||
revs.length === 1 ? Translations.t.reviews.title_singular.Clone() :
|
revs.length === 1 ? Translations.t.reviews.title_singular.Clone() :
|
||||||
Translations.t.reviews.title.Clone()
|
Translations.t.reviews.title
|
||||||
.Subs({count: "" + revs.length}),
|
.Subs({count: "" + revs.length}),
|
||||||
`https://mangrove.reviews/search?sub=${encodeURIComponent(subject)}`,
|
`https://mangrove.reviews/search?sub=${encodeURIComponent(subject)}`,
|
||||||
true
|
true
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||||
import Wikidata, {WikidataResponse} from "../../Logic/Web/Wikidata";
|
import Wikidata, {WikidataResponse} from "../../Logic/Web/Wikidata";
|
||||||
import {Translation} from "../i18n/Translation";
|
import {Translation, TypedTranslation} from "../i18n/Translation";
|
||||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||||
import Loading from "../Base/Loading";
|
import Loading from "../Base/Loading";
|
||||||
import Translations from "../i18n/Translations";
|
import Translations from "../i18n/Translations";
|
||||||
|
@ -22,7 +22,7 @@ export default class WikidataPreviewBox extends VariableUiElement {
|
||||||
private static extraProperties: {
|
private static extraProperties: {
|
||||||
requires?: { p: number, q?: number }[],
|
requires?: { p: number, q?: number }[],
|
||||||
property: string,
|
property: string,
|
||||||
display: Translation | Map<string, string | (() => BaseUIElement) /*If translation: Subs({value: * }) */>
|
display: TypedTranslation<{value}> | Map<string, string | (() => BaseUIElement) /*If translation: Subs({value: * }) */>
|
||||||
}[] = [
|
}[] = [
|
||||||
{
|
{
|
||||||
requires: WikidataPreviewBox.isHuman,
|
requires: WikidataPreviewBox.isHuman,
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import Locale from "./Locale";
|
import Locale from "./Locale";
|
||||||
import {Utils} from "../../Utils";
|
import {Utils} from "../../Utils";
|
||||||
import BaseUIElement from "../BaseUIElement";
|
import BaseUIElement from "../BaseUIElement";
|
||||||
import Link from "../Base/Link";
|
|
||||||
import Svg from "../../Svg";
|
|
||||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
|
||||||
import LinkToWeblate from "../Base/LinkToWeblate";
|
import LinkToWeblate from "../Base/LinkToWeblate";
|
||||||
|
|
||||||
export class Translation extends BaseUIElement {
|
export class Translation extends BaseUIElement {
|
||||||
|
@ -165,24 +162,6 @@ export class Translation extends BaseUIElement {
|
||||||
return this.SupportedLanguages().map(lng => this.translations[lng]);
|
return this.SupportedLanguages().map(lng => this.translations[lng]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Substitutes text in a translation.
|
|
||||||
* If a translation is passed, it'll be fused
|
|
||||||
*
|
|
||||||
* // Should replace simple keys
|
|
||||||
* new Translation({"en": "Some text {key}"}).Subs({key: "xyz"}).textFor("en") // => "Some text xyz"
|
|
||||||
*
|
|
||||||
* // Should fuse translations
|
|
||||||
* const subpart = new Translation({"en": "subpart","nl":"onderdeel"})
|
|
||||||
* const tr = new Translation({"en": "Full sentence with {part}", nl: "Volledige zin met {part}"})
|
|
||||||
* const subbed = tr.Subs({part: subpart})
|
|
||||||
* subbed.textFor("en") // => "Full sentence with subpart"
|
|
||||||
* subbed.textFor("nl") // => "Volledige zin met onderdeel"
|
|
||||||
*/
|
|
||||||
public Subs(text: any, context?: string): Translation {
|
|
||||||
return this.OnEveryLanguage((template, lang) => Utils.SubstituteKeys(template, text, lang), context)
|
|
||||||
}
|
|
||||||
|
|
||||||
public OnEveryLanguage(f: (s: string, language: string) => string, context?: string): Translation {
|
public OnEveryLanguage(f: (s: string, language: string) => string, context?: string): Translation {
|
||||||
const newTranslations = {};
|
const newTranslations = {};
|
||||||
for (const lang in this.translations) {
|
for (const lang in this.translations) {
|
||||||
|
@ -278,5 +257,28 @@ export class Translation extends BaseUIElement {
|
||||||
return this.txt
|
return this.txt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TypedTranslation<T> extends Translation {
|
||||||
|
constructor(translations: object, context?: string) {
|
||||||
|
super(translations, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Substitutes text in a translation.
|
||||||
|
* If a translation is passed, it'll be fused
|
||||||
|
*
|
||||||
|
* // Should replace simple keys
|
||||||
|
* new TypedTranslation<object>({"en": "Some text {key}"}).Subs({key: "xyz"}).textFor("en") // => "Some text xyz"
|
||||||
|
*
|
||||||
|
* // Should fuse translations
|
||||||
|
* const subpart = new Translation({"en": "subpart","nl":"onderdeel"})
|
||||||
|
* const tr = new TypedTranslation<object>({"en": "Full sentence with {part}", nl: "Volledige zin met {part}"})
|
||||||
|
* const subbed = tr.Subs({part: subpart})
|
||||||
|
* subbed.textFor("en") // => "Full sentence with subpart"
|
||||||
|
* subbed.textFor("nl") // => "Volledige zin met onderdeel"
|
||||||
|
*/
|
||||||
|
Subs(text: T, context?: string): Translation {
|
||||||
|
return this.OnEveryLanguage((template, lang) => Utils.SubstituteKeys(template, text, lang), context)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||||
import {Translation} from "./Translation";
|
import {Translation, TypedTranslation} from "./Translation";
|
||||||
import BaseUIElement from "../BaseUIElement";
|
import BaseUIElement from "../BaseUIElement";
|
||||||
import * as known_languages from "../../assets/generated/used_languages.json"
|
import * as known_languages from "../../assets/generated/used_languages.json"
|
||||||
import CompiledTranslations from "../../assets/generated/CompiledTranslations";
|
import CompiledTranslations from "../../assets/generated/CompiledTranslations";
|
||||||
|
@ -22,7 +22,7 @@ export default class Translations {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static T(t: string | any, context = undefined): Translation {
|
static T(t: string | any, context = undefined): TypedTranslation<object> {
|
||||||
if (t === undefined || t === null) {
|
if (t === undefined || t === null) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -30,17 +30,17 @@ export default class Translations {
|
||||||
t = "" + t
|
t = "" + t
|
||||||
}
|
}
|
||||||
if (typeof t === "string") {
|
if (typeof t === "string") {
|
||||||
return new Translation({"*": t}, context);
|
return new TypedTranslation({"*": t}, context);
|
||||||
}
|
}
|
||||||
if (t.render !== undefined) {
|
if (t.render !== undefined) {
|
||||||
const msg = "Creating a translation, but this object contains a 'render'-field. Use the translation directly"
|
const msg = "Creating a translation, but this object contains a 'render'-field. Use the translation directly"
|
||||||
console.error(msg, t);
|
console.error(msg, t);
|
||||||
throw msg
|
throw msg
|
||||||
}
|
}
|
||||||
if (t instanceof Translation) {
|
if (t instanceof TypedTranslation) {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
return new Translation(t, context);
|
return new TypedTranslation(t, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -42,11 +42,6 @@
|
||||||
"getStartedLogin": "Entra no OpenStreetMap para comezar",
|
"getStartedLogin": "Entra no OpenStreetMap para comezar",
|
||||||
"getStartedNewAccount": " ou <a href='https://www.openstreetmap.org/user/new' target='_blank'>crea unha nova conta</a>",
|
"getStartedNewAccount": " ou <a href='https://www.openstreetmap.org/user/new' target='_blank'>crea unha nova conta</a>",
|
||||||
"goToInbox": "Abrir mensaxes",
|
"goToInbox": "Abrir mensaxes",
|
||||||
"index": {
|
|
||||||
"intro": "O MapComplete é un visor e editor do OpenStreetMap, que te amosa información sobre un tema específico.",
|
|
||||||
"pickTheme": "Escolle un tema para comezar.",
|
|
||||||
"title": "Benvido ao MapComplete"
|
|
||||||
},
|
|
||||||
"layerSelection": {
|
"layerSelection": {
|
||||||
"title": "Seleccionar capas",
|
"title": "Seleccionar capas",
|
||||||
"zoomInToSeeThisLayer": "Achégate para ver esta capa"
|
"zoomInToSeeThisLayer": "Achégate para ver esta capa"
|
||||||
|
|
|
@ -97,12 +97,6 @@
|
||||||
"backToMapcomplete": "Terug naar het themaoverzicht",
|
"backToMapcomplete": "Terug naar het themaoverzicht",
|
||||||
"backgroundMap": "Achtergrondkaart",
|
"backgroundMap": "Achtergrondkaart",
|
||||||
"cancel": "Annuleren",
|
"cancel": "Annuleren",
|
||||||
"centerMessage": {
|
|
||||||
"loadingData": "Data wordt geladen…",
|
|
||||||
"ready": "Klaar!",
|
|
||||||
"retrying": "Data inladen mislukt. Opnieuw proberen over {count} seconden…",
|
|
||||||
"zoomIn": "Zoom in om de data te zien en te bewerken"
|
|
||||||
},
|
|
||||||
"confirm": "Bevestigen",
|
"confirm": "Bevestigen",
|
||||||
"customThemeIntro": "<h3>Onofficiële thema's</h3>De onderstaande thema's heb je eerder bezocht en zijn gemaakt door andere OpenStreetMappers.",
|
"customThemeIntro": "<h3>Onofficiële thema's</h3>De onderstaande thema's heb je eerder bezocht en zijn gemaakt door andere OpenStreetMappers.",
|
||||||
"download": {
|
"download": {
|
||||||
|
@ -132,12 +126,6 @@
|
||||||
"histogram": {
|
"histogram": {
|
||||||
"error_loading": "Kan het histogram niet laden"
|
"error_loading": "Kan het histogram niet laden"
|
||||||
},
|
},
|
||||||
"index": {
|
|
||||||
"#": "Deze teksten worden getoond boven de themaknoppen als er geen thema is geladen",
|
|
||||||
"intro": "MapComplete is een OpenStreetMap applicatie waar informatie over een specifiek thema bekeken en aangepast kan worden.",
|
|
||||||
"pickTheme": "Kies hieronder een thema om te beginnen.",
|
|
||||||
"title": "Welkom bij MapComplete"
|
|
||||||
},
|
|
||||||
"layerSelection": {
|
"layerSelection": {
|
||||||
"title": "Selecteer lagen",
|
"title": "Selecteer lagen",
|
||||||
"zoomInToSeeThisLayer": "Vergroot de kaart om deze laag te zien"
|
"zoomInToSeeThisLayer": "Vergroot de kaart om deze laag te zien"
|
||||||
|
@ -199,22 +187,6 @@
|
||||||
"readYourMessages": "Gelieve eerst je berichten op OpenStreetMap te lezen alvorens nieuwe punten toe te voegen.",
|
"readYourMessages": "Gelieve eerst je berichten op OpenStreetMap te lezen alvorens nieuwe punten toe te voegen.",
|
||||||
"removeLocationHistory": "Verwijder de geschiedenis aan locaties",
|
"removeLocationHistory": "Verwijder de geschiedenis aan locaties",
|
||||||
"returnToTheMap": "Ga terug naar de kaart",
|
"returnToTheMap": "Ga terug naar de kaart",
|
||||||
"reviews": {
|
|
||||||
"affiliated_reviewer_warning": "(Review door betrokkene)",
|
|
||||||
"attribution": "De beoordelingen worden voorzien door <a href=\"https://mangrove.reviews/\" target=\"_blank\">Mangrove Reviews</a> en zijn beschikbaar onder de<a href=\"https://mangrove.reviews/terms#8-licensing-of-content\" target=\"_blank\">CC-BY 4.0-licentie</a>.",
|
|
||||||
"i_am_affiliated": "<span>Ik ben persoonlijk betrokken</span><br/><span class='subtle'>Vink aan indien je de oprichter, maker, werknemer, ... of dergelijke bent</span>",
|
|
||||||
"name_required": "De naam van dit object moet gekend zijn om een review te kunnen maken",
|
|
||||||
"no_rating": "Geen score bekend",
|
|
||||||
"no_reviews_yet": "Er zijn nog geen beoordelingen. Wees de eerste om een beoordeling te schrijven en help open data en het bedrijf!",
|
|
||||||
"plz_login": "Meld je aan om een beoordeling te geven",
|
|
||||||
"posting_as": "Ingelogd als",
|
|
||||||
"saved": "<span class='thanks'>Bedankt om je beoordeling te delen!</span>",
|
|
||||||
"saving_review": "Opslaan…",
|
|
||||||
"title": "{count} beoordelingen",
|
|
||||||
"title_singular": "Eén beoordeling",
|
|
||||||
"tos": "Als je je review publiceert, ga je akkoord met de <a href='https://mangrove.reviews/terms' target='_blank'>de gebruiksvoorwaarden en privacy policy van Mangrove.reviews</a>",
|
|
||||||
"write_a_comment": "Schrijf een beoordeling…"
|
|
||||||
},
|
|
||||||
"save": "Opslaan",
|
"save": "Opslaan",
|
||||||
"search": {
|
"search": {
|
||||||
"error": "Niet gelukt...",
|
"error": "Niet gelukt...",
|
||||||
|
|
112
langs/pl.json
112
langs/pl.json
|
@ -35,121 +35,9 @@
|
||||||
"cancel": "Anuluj",
|
"cancel": "Anuluj",
|
||||||
"customThemeIntro": "<h3>Motywy własne</h3>Są to wcześniej odwiedzone motywy stworzone przez użytkowników.",
|
"customThemeIntro": "<h3>Motywy własne</h3>Są to wcześniej odwiedzone motywy stworzone przez użytkowników.",
|
||||||
"fewChangesBefore": "Proszę odpowiedzieć na kilka pytań dotyczących istniejących punktów przed dodaniem nowego punktu.",
|
"fewChangesBefore": "Proszę odpowiedzieć na kilka pytań dotyczących istniejących punktów przed dodaniem nowego punktu.",
|
||||||
"general": {
|
|
||||||
"about": "Łatwo edytuj i dodaj OpenStreetMap dla określonego motywu",
|
|
||||||
"aboutMapcomplete": "<h3>O MapComplete</h3><p>Dzięki MapComplete możesz wzbogacić OpenStreetMap o informacje na <b>pojedynczy temat.</b> Odpowiedz na kilka pytań, a w ciągu kilku minut Twój wkład będzie dostępny na całym świecie! Opiekun <b>tematu</b> definiuje elementy, pytania i języki dla tematu.</p><h3>Dowiedz się więcej</h3><p>MapComplete zawsze <b>oferuje następny krok</b>, by dowiedzieć się więcej o OpenStreetMap.</p><ul><li>Po osadzeniu na stronie internetowej, element iframe łączy się z pełnoekranowym MapComplete</li><li>Wersja pełnoekranowa oferuje informacje o OpenStreetMap</li><li>Przeglądanie działa bez logowania, ale edycja wymaga loginu OSM.</li><li>Jeżeli nie jesteś zalogowany, zostaniesz poproszony o zalogowanie się</li><li>Po udzieleniu odpowiedzi na jedno pytanie, możesz dodać nowe punkty do mapy</li><li>Po chwili wyświetlane są rzeczywiste tagi OSM, które później linkują do wiki</li></ul><p></p><br><p>Zauważyłeś <b>problem</b>? Czy masz <b>prośbę o dodanie jakiejś funkcji</b>? Chcesz <b>pomóc w tłumaczeniu</b>? Udaj się do <a href=\"https://github.com/pietervdvn/MapComplete\" target=\"_blank\">kodu źródłowego</a> lub <a href=\"https://github.com/pietervdvn/MapComplete/issues\" target=\"_blank\">issue trackera.</a> </p><p> Chcesz zobaczyć <b>swoje postępy</b>? Śledź liczbę edycji na <a href=\"{osmcha_link}\" target=\"_blank\">OsmCha</a>.</p>",
|
|
||||||
"add": {
|
|
||||||
"addNew": "Dodaj nową {category} tutaj",
|
|
||||||
"confirmButton": "Dodaj tutaj {category}.<br><div class=\"alert\">Twój dodatek jest widoczny dla wszystkich</div>",
|
|
||||||
"confirmIntro": "<h3>Czy dodać tutaj {title}?</h3> Punkt, który tutaj utworzysz, będzie <b>widoczny dla wszystkich</b>. Proszę, dodawaj rzeczy do mapy tylko wtedy, gdy naprawdę istnieją. Wiele aplikacji korzysta z tych danych.",
|
|
||||||
"intro": "Kliknąłeś gdzieś, gdzie nie są jeszcze znane żadne dane.<br>",
|
|
||||||
"layerNotEnabled": "Warstwa {layer} nie jest włączona. Włącz tę warstwę, aby dodać punkt",
|
|
||||||
"openLayerControl": "Otwórz okno sterowania warstwą",
|
|
||||||
"pleaseLogin": "<a class=\"activate-osm-authentication\">Zaloguj się, aby dodać nowy punkt</a>",
|
|
||||||
"stillLoading": "Dane wciąż się ładują. Poczekaj chwilę, zanim dodasz nowy punkt.",
|
|
||||||
"title": "Czy dodać nowy punkt?",
|
|
||||||
"zoomInFurther": "Powiększ jeszcze bardziej, aby dodać punkt."
|
|
||||||
},
|
|
||||||
"backgroundMap": "Tło mapy",
|
|
||||||
"cancel": "Anuluj",
|
|
||||||
"customThemeIntro": "<h3>Motywy własne</h3>Są to wcześniej odwiedzone motywy stworzone przez użytkowników.",
|
|
||||||
"fewChangesBefore": "Proszę odpowiedzieć na kilka pytań dotyczących istniejących punktów przed dodaniem nowego punktu.",
|
|
||||||
"getStartedLogin": "Zaloguj się za pomocą OpenStreetMap, aby rozpocząć",
|
|
||||||
"getStartedNewAccount": " lub <a href=\"https://www.openstreetmap.org/user/new\" target=\"_blank\">utwórz nowe konto</a>",
|
|
||||||
"goToInbox": "Otwórz skrzynkę odbiorczą",
|
|
||||||
"layerSelection": {
|
|
||||||
"title": "Wybierz warstwy",
|
|
||||||
"zoomInToSeeThisLayer": "Powiększ, aby zobaczyć tę warstwę"
|
|
||||||
},
|
|
||||||
"loginToStart": "Zaloguj się, aby odpowiedzieć na to pytanie",
|
|
||||||
"loginWithOpenStreetMap": "Zaloguj z OpenStreetMap",
|
|
||||||
"nameInlineQuestion": "Nazwa tej {category} to $$$",
|
|
||||||
"noNameCategory": "{category} bez nazwy",
|
|
||||||
"noTagsSelected": "Nie wybrano tagów",
|
|
||||||
"number": "numer",
|
|
||||||
"oneSkippedQuestion": "Jedno pytanie zostało pominięte",
|
|
||||||
"opening_hours": {
|
|
||||||
"closed_permanently": "Zamknięte na nieokreślony czas",
|
|
||||||
"closed_until": "Zamknięte do {date}",
|
|
||||||
"error_loading": "Błąd: nie można zwizualizować tych godzin otwarcia.",
|
|
||||||
"not_all_rules_parsed": "Godziny otwarcia tego sklepu są skomplikowane. Następujące reguły są ignorowane w elemencie wejściowym:",
|
|
||||||
"openTill": "do",
|
|
||||||
"open_24_7": "Otwarte przez całą dobę",
|
|
||||||
"open_during_ph": "W czasie świąt państwowych udogodnienie to jest",
|
|
||||||
"opensAt": "z",
|
|
||||||
"ph_closed": "zamknięte",
|
|
||||||
"ph_not_known": " ",
|
|
||||||
"ph_open": "otwarte"
|
|
||||||
},
|
|
||||||
"osmLinkTooltip": "Zobacz ten obiekt na OpenStreetMap, aby uzyskać historię i więcej opcji edycji",
|
|
||||||
"pickLanguage": "Wybierz język: ",
|
|
||||||
"questions": {
|
|
||||||
"emailIs": "Adres e-mail {category} to <a href=\"mailto:{email}\" target=\"_blank\">{email}</a>",
|
|
||||||
"emailOf": "Jaki jest adres e-mail {category}?",
|
|
||||||
"phoneNumberIs": "Numer telefonu {category} to <a target=\"_blank\">{phone}</a>",
|
|
||||||
"phoneNumberOf": "Jaki jest numer telefonu do {category}?",
|
|
||||||
"websiteIs": "Strona internetowa: <a href=\"{website}\" target=\"_blank\">{website}</a>",
|
|
||||||
"websiteOf": "Jaka jest strona internetowa {category}?"
|
|
||||||
},
|
|
||||||
"readYourMessages": "Przeczytaj wszystkie wiadomości OpenStreetMap przed dodaniem nowego punktu.",
|
|
||||||
"returnToTheMap": "Wróć do mapy",
|
|
||||||
"save": "Zapisz",
|
|
||||||
"search": {
|
|
||||||
"error": "Coś poszło nie tak…",
|
|
||||||
"nothing": "Nic nie znaleziono…",
|
|
||||||
"search": "Wyszukaj lokalizację",
|
|
||||||
"searching": "Szukanie…"
|
|
||||||
},
|
|
||||||
"sharescreen": {
|
|
||||||
"addToHomeScreen": "<h3> Dodaj do ekranu głównego</h3>Możesz łatwo dodać tę stronę do ekranu głównego smartfona, aby poczuć się jak w domu. Kliknij przycisk \"Dodaj do ekranu głównego\" na pasku adresu URL, aby to zrobić.",
|
|
||||||
"copiedToClipboard": "Link został skopiowany do schowka",
|
|
||||||
"editThemeDescription": "Dodaj lub zmień pytania do tego motywu mapy",
|
|
||||||
"editThisTheme": "Edytuj ten motyw",
|
|
||||||
"embedIntro": "<h3>Umieść na swojej stronie internetowej</h3>Proszę, umieść tę mapę na swojej stronie internetowej. <br>Zachęcamy cię do tego - nie musisz nawet pytać o zgodę. <br>Jest ona darmowa i zawsze będzie. Im więcej osób jej używa, tym bardziej staje się wartościowa.",
|
|
||||||
"fsAddNew": "Włącz przycisk \"Dodaj nowe POI\"",
|
|
||||||
"fsGeolocation": "Włącz przycisk „Zlokalizuj mnie” (tylko na urządzeniach mobilnych)",
|
|
||||||
"fsIncludeCurrentBackgroundMap": "Dołącz bieżący wybór tła <b>{name}</b>",
|
|
||||||
"fsIncludeCurrentLayers": "Uwzględnij wybór bieżącej warstwy",
|
|
||||||
"fsIncludeCurrentLocation": "Uwzględnij bieżącą lokalizację",
|
|
||||||
"fsLayerControlToggle": "Zacznij od rozwiniętej kontroli warstw",
|
|
||||||
"fsLayers": "Włącz kontrolę warstw",
|
|
||||||
"fsSearch": "Włącz pasek wyszukiwania",
|
|
||||||
"fsUserbadge": "Włącz przycisk logowania",
|
|
||||||
"fsWelcomeMessage": "Pokaż wyskakujące okienko wiadomości powitalnej i powiązane zakładki",
|
|
||||||
"intro": "<h3> Udostępnij tę mapę</h3> Udostępnij tę mapę, kopiując poniższy link i wysyłając ją do przyjaciół i rodziny:",
|
|
||||||
"thanksForSharing": "Dzięki za udostępnienie!"
|
|
||||||
},
|
|
||||||
"skip": "Pomiń to pytanie",
|
|
||||||
"skippedQuestions": "Niektóre pytania są pominięte",
|
|
||||||
"weekdays": {
|
|
||||||
"abbreviations": {
|
|
||||||
"friday": "Pt",
|
|
||||||
"monday": "Pn",
|
|
||||||
"saturday": "Sob",
|
|
||||||
"sunday": "Niedz",
|
|
||||||
"thursday": "Czw",
|
|
||||||
"tuesday": "Wt",
|
|
||||||
"wednesday": "Śr"
|
|
||||||
},
|
|
||||||
"friday": "Piątek",
|
|
||||||
"monday": "Poniedziałek",
|
|
||||||
"saturday": "Sobota",
|
|
||||||
"sunday": "Niedziela",
|
|
||||||
"thursday": "Czwartek",
|
|
||||||
"tuesday": "Wtorek",
|
|
||||||
"wednesday": "Środa"
|
|
||||||
},
|
|
||||||
"welcomeBack": "Jesteś zalogowany, witaj z powrotem!"
|
|
||||||
},
|
|
||||||
"getStartedLogin": "Zaloguj się za pomocą OpenStreetMap, aby rozpocząć",
|
"getStartedLogin": "Zaloguj się za pomocą OpenStreetMap, aby rozpocząć",
|
||||||
"getStartedNewAccount": " lub <a href=\"https://www.openstreetmap.org/user/new\" target=\"_blank\">utwórz nowe konto</a>",
|
"getStartedNewAccount": " lub <a href=\"https://www.openstreetmap.org/user/new\" target=\"_blank\">utwórz nowe konto</a>",
|
||||||
"goToInbox": "Otwórz skrzynkę odbiorczą",
|
"goToInbox": "Otwórz skrzynkę odbiorczą",
|
||||||
"index": {
|
|
||||||
"#": "Te teksty są wyświetlane nad przyciskami motywu, gdy nie jest załadowany żaden motyw",
|
|
||||||
"intro": "MapComplete to przeglądarka i edytor OpenStreetMap, który pokazuje informacje podzielone według tematu.",
|
|
||||||
"pickTheme": "Wybierz temat poniżej, aby rozpocząć.",
|
|
||||||
"title": "Witaj w MapComplete"
|
|
||||||
},
|
|
||||||
"layerSelection": {
|
"layerSelection": {
|
||||||
"title": "Wybierz warstwy",
|
"title": "Wybierz warstwy",
|
||||||
"zoomInToSeeThisLayer": "Powiększ, aby zobaczyć tę warstwę"
|
"zoomInToSeeThisLayer": "Powiększ, aby zobaczyć tę warstwę"
|
||||||
|
|
|
@ -90,130 +90,6 @@
|
||||||
"title": "下載可視的資料"
|
"title": "下載可視的資料"
|
||||||
},
|
},
|
||||||
"fewChangesBefore": "請先回答有關既有節點的問題再來新增新節點。",
|
"fewChangesBefore": "請先回答有關既有節點的問題再來新增新節點。",
|
||||||
"general": {
|
|
||||||
"about": "相當容易編輯,而且能為開放街圖新增特定主題",
|
|
||||||
"aboutMapcomplete": "<h3>關於 MapComplete</h3><p>使用 MapComplete 你可以藉由<b>單一主題</b>豐富開放街圖的圖資。回答幾個問題,然後幾分鐘之內你的貢獻立刻就傳遍全球!<b>主題維護者</b>定議主題的元素、問題與語言。</p><h3>發現更多</h3><p>MapComplete 總是提供學習更多開放街圖<b>下一步的知識</b>。</p><ul><li>當你內嵌網站,網頁內嵌會連結到全螢幕的 MapComplete</li><li>全螢幕的版本提供關於開放街圖的資訊</li><li>不登入檢視成果,但是要編輯則需登入 OSM。</li><li>如果你沒有登入,你會被要求先登入</li><li>當你回答單一問題時,你可以在地圖新增新的節點</li><li>過了一陣子,實際的 OSM-標籤會顯示,之後會連結到 wiki</li></ul><p></p><br><p>你有注意到<b>問題</b>嗎?你想請求<b>功能</b>嗎?想要<b>幫忙翻譯</b>嗎?來到<a href=\"https://github.com/pietervdvn/MapComplete\" target=\"_blank\">原始碼</a>或是<a href=\"https://github.com/pietervdvn/MapComplete/issues\" target=\"_blank\">問題追蹤器。</a></p><p>想要看到<b>你的進度</b>嗎?到<a href=\"{osmcha_link}\" target=\"_blank\">OsmCha</a>追蹤編輯數。</p>",
|
|
||||||
"add": {
|
|
||||||
"addNew": "在這裡新增新的 {category}",
|
|
||||||
"confirmButton": "在此新增 {category}。<br><div class=\"alert\">大家都可以看到您新增的內容</div>",
|
|
||||||
"confirmIntro": "<h3>在這裡新增 {title} ?</h3>你在這裡新增的節點<b>所有人都看得到</b>。請只有在確定有物件存在的情形下才新增上去,許多應用程式都使用這份資料。",
|
|
||||||
"intro": "您點擊處目前未有已知的資料。<br>",
|
|
||||||
"layerNotEnabled": "圖層 {layer} 目前無法使用,請先啟用這圖層再加新的節點",
|
|
||||||
"openLayerControl": "開啟圖層控制框",
|
|
||||||
"pleaseLogin": "<a class=\"activate-osm-authentication\">請先登入來新增節點</a>",
|
|
||||||
"stillLoading": "目前仍在載入資料,請稍後再來新增節點。",
|
|
||||||
"title": "新增新的節點?",
|
|
||||||
"zoomInFurther": "放大來新增新的節點。"
|
|
||||||
},
|
|
||||||
"attribution": {
|
|
||||||
"attributionContent": "<p>所有資料由<a href=\"https://osm.org\" target=\"_blank\">開放街圖</a>提供,在<a href=\"https://osm.org/copyright\" target=\"_blank\">開放資料庫授權條款</a>之下自由再利用。</p>",
|
|
||||||
"attributionTitle": "署名通知",
|
|
||||||
"codeContributionsBy": "MapComplete 是由 {contributors} 和其他 <a href=\"https://github.com/pietervdvn/MapComplete/graphs/contributors\" target=\"_blank\">{hiddenCount} 位貢獻者</a>構建而成",
|
|
||||||
"iconAttribution": {
|
|
||||||
"title": "使用的圖示"
|
|
||||||
},
|
|
||||||
"mapContributionsBy": "目前檢視的資料由 {contributors} 貢獻編輯",
|
|
||||||
"mapContributionsByAndHidden": "目前顯到的資料是由 {contributors} 和其他 {hiddenCount} 位貢獻者編輯貢獻",
|
|
||||||
"themeBy": "由 {author} 維護主題"
|
|
||||||
},
|
|
||||||
"backgroundMap": "背景地圖",
|
|
||||||
"cancel": "取消",
|
|
||||||
"customThemeIntro": "<h3>客製化主題</h3>觀看這些先前使用者創造的主題。",
|
|
||||||
"fewChangesBefore": "請先回答有關既有節點的問題再來新增新節點。",
|
|
||||||
"getStartedLogin": "登入開放街圖帳號來開始",
|
|
||||||
"getStartedNewAccount": " 或是 <a href=\"https://www.openstreetmap.org/user/new\" target=\"_blank\">註冊新帳號</a>",
|
|
||||||
"goToInbox": "開啟訊息框",
|
|
||||||
"layerSelection": {
|
|
||||||
"title": "選擇圖層",
|
|
||||||
"zoomInToSeeThisLayer": "放大來看這個圖層"
|
|
||||||
},
|
|
||||||
"loginToStart": "登入之後來回答這問題",
|
|
||||||
"loginWithOpenStreetMap": "用開放街圖帳號登入",
|
|
||||||
"morescreen": {
|
|
||||||
"createYourOwnTheme": "從零開始建立你的 MapComplete 主題",
|
|
||||||
"intro": "<h3>看更多主題地圖?</h3>您喜歡蒐集地理資料嗎?<br>還有更多主題。",
|
|
||||||
"requestATheme": "如果你有客製化要求,請到問題追踪器那邊提出要求",
|
|
||||||
"streetcomplete": "行動裝置另有類似的應用程式 <a class=\"underline hover:text-blue-800\" href=\"https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete\" target=\"_blank\">StreetComplete</a>。"
|
|
||||||
},
|
|
||||||
"nameInlineQuestion": "這個 {category} 的名稱是 $$$",
|
|
||||||
"noNameCategory": "{category} 沒有名稱",
|
|
||||||
"noTagsSelected": "沒有選取標籤",
|
|
||||||
"number": "號碼",
|
|
||||||
"oneSkippedQuestion": "跳過一個問題",
|
|
||||||
"openStreetMapIntro": "<h3>開放的地圖</h3><p>如果有一份地圖,任何人都能自由使用與編輯,單一的地圖能夠儲存所有地理相關資訊?這樣不就很酷嗎?接著,所有的網站使用不同的、範圍小的,不相容的地圖 (通常也都過時了),也就不再需要了。</p><p><b><a href=\"https://OpenStreetMap.org\" target=\"_blank\">開放街圖</a></b>就是這樣的地圖,人人都能免費這些圖資 (只要<a href=\"https://osm.org/copyright\" target=\"_blank\">署名與公開變動這資料</a>)。只要遵循這些,任何人都能自由新增新資料與修正錯誤,這些網站也都使用開放街圖,資料也都來自開放街圖,你的答案與修正也會加到開放街圖上面。</p><p>許多人與應用程式已經採用開放街圖了:<a href=\"https://organicmaps.app//\" target=\"_blank\">Organic Maps</a>、<a href=\"https://osmAnd.net\" target=\"_blank\">OsmAnd</a>,還有 Facebook、Instagram,蘋果地圖、Bing 地圖(部分)採用開放街圖。如果你在開放街圖上變動資料,也會同時影響這些應用 - 在他們下次更新資料之後!</p>",
|
|
||||||
"opening_hours": {
|
|
||||||
"closed_permanently": "不清楚關閉多久了",
|
|
||||||
"closed_until": "{date} 起關閉",
|
|
||||||
"error_loading": "錯誤:無法視覺化開放時間。",
|
|
||||||
"not_all_rules_parsed": "這間店的開放時間相當複雜,在輸入元素時忽略接下來的規則:",
|
|
||||||
"openTill": "結束時間",
|
|
||||||
"open_24_7": "24小時營業",
|
|
||||||
"open_during_ph": "國定假日的時候,這個場所是",
|
|
||||||
"opensAt": "開始時間",
|
|
||||||
"ph_closed": "無營業",
|
|
||||||
"ph_not_known": " ",
|
|
||||||
"ph_open": "有營業"
|
|
||||||
},
|
|
||||||
"osmLinkTooltip": "在開放街圖歷史和更多編輯選項下面來檢視這物件",
|
|
||||||
"pickLanguage": "選擇語言: ",
|
|
||||||
"questions": {
|
|
||||||
"emailIs": "{category} 的電子郵件地址是<a href=\"mailto:{email}\" target=\"_blank\">{email}</a>",
|
|
||||||
"emailOf": "{category} 的電子郵件地址是?",
|
|
||||||
"phoneNumberIs": "此 {category} 的電話號碼為 <a target=\"_blank\">{phone}</a>",
|
|
||||||
"phoneNumberOf": "{category} 的電話號碼是?",
|
|
||||||
"websiteIs": "網站:<a href=\"{website}\" target=\"_blank\">{website}</a>",
|
|
||||||
"websiteOf": "{category} 的網站網址是?"
|
|
||||||
},
|
|
||||||
"readYourMessages": "請先閱讀開放街圖訊息之前再來新增新節點。",
|
|
||||||
"returnToTheMap": "回到地圖",
|
|
||||||
"save": "儲存",
|
|
||||||
"search": {
|
|
||||||
"error": "有狀況發生了…",
|
|
||||||
"nothing": "沒有找到…",
|
|
||||||
"search": "搜尋地點",
|
|
||||||
"searching": "搜尋中…"
|
|
||||||
},
|
|
||||||
"sharescreen": {
|
|
||||||
"addToHomeScreen": "<h3>新增到您的主畫面</h3>您可以輕易將這網站新增到您智慧型手機的主畫面,在網址列點選「新增到主畫面按鈕」來做這件事情。",
|
|
||||||
"copiedToClipboard": "複製連結到簡貼簿",
|
|
||||||
"editThemeDescription": "新增或改變這個地圖的問題",
|
|
||||||
"editThisTheme": "編輯這個主題",
|
|
||||||
"embedIntro": "<h3>嵌入到你的網站</h3>請考慮將這份地圖嵌入您的網站。<br>地圖毋須額外授權,非常歡迎您多加利用。<br>一切都是免費的,而且之後也是免費的,越有更多人使用,則越顯得它的價值。",
|
|
||||||
"fsAddNew": "啟用'新增新的興趣點'按鈕",
|
|
||||||
"fsGeolocation": "啟用'地理定位自身'按鈕 (只有行動版本)",
|
|
||||||
"fsIncludeCurrentBackgroundMap": "包含目前背景選擇<b>{name}</b>",
|
|
||||||
"fsIncludeCurrentLayers": "包含目前選擇圖層",
|
|
||||||
"fsIncludeCurrentLocation": "包含目前位置",
|
|
||||||
"fsLayerControlToggle": "開始時擴展圖層控制",
|
|
||||||
"fsLayers": "啟用圖層控制",
|
|
||||||
"fsSearch": "啟用搜尋列",
|
|
||||||
"fsUserbadge": "啟用登入按鈕",
|
|
||||||
"fsWelcomeMessage": "顯示歡迎訊息以及相關頁籤",
|
|
||||||
"intro": "<h3>分享這地圖</h3>複製下面的連結來向朋友與家人分享這份地圖:",
|
|
||||||
"thanksForSharing": "感謝分享!"
|
|
||||||
},
|
|
||||||
"skip": "跳過這問題",
|
|
||||||
"skippedQuestions": "有些問題已經跳過了",
|
|
||||||
"weekdays": {
|
|
||||||
"abbreviations": {
|
|
||||||
"friday": "星期五",
|
|
||||||
"monday": "星期一",
|
|
||||||
"saturday": "星期六",
|
|
||||||
"sunday": "星期日",
|
|
||||||
"thursday": "星期四",
|
|
||||||
"tuesday": "星期二",
|
|
||||||
"wednesday": "星期三"
|
|
||||||
},
|
|
||||||
"friday": "星期五",
|
|
||||||
"monday": "星期一",
|
|
||||||
"saturday": "星期六",
|
|
||||||
"sunday": "星期日",
|
|
||||||
"thursday": "星期四",
|
|
||||||
"tuesday": "星期二",
|
|
||||||
"wednesday": "星期三"
|
|
||||||
},
|
|
||||||
"welcomeBack": "你已經登入了,歡迎回來!"
|
|
||||||
},
|
|
||||||
"getStartedLogin": "登入開放街圖帳號來開始",
|
"getStartedLogin": "登入開放街圖帳號來開始",
|
||||||
"getStartedNewAccount": " 或是 <a href=\"https://www.openstreetmap.org/user/new\" target=\"_blank\">註冊新帳號</a>",
|
"getStartedNewAccount": " 或是 <a href=\"https://www.openstreetmap.org/user/new\" target=\"_blank\">註冊新帳號</a>",
|
||||||
"goToInbox": "開啟訊息框",
|
"goToInbox": "開啟訊息框",
|
||||||
|
|
|
@ -2,8 +2,6 @@ import * as fs from "fs";
|
||||||
import {readFileSync, writeFileSync} from "fs";
|
import {readFileSync, writeFileSync} from "fs";
|
||||||
import {Utils} from "../Utils";
|
import {Utils} from "../Utils";
|
||||||
import ScriptUtils from "./ScriptUtils";
|
import ScriptUtils from "./ScriptUtils";
|
||||||
import {AllKnownLayouts} from "../Customizations/AllKnownLayouts";
|
|
||||||
import TranslatorsPanel from "../UI/BigComponents/TranslatorsPanel";
|
|
||||||
|
|
||||||
const knownLanguages = ["en", "nl", "de", "fr", "es", "gl", "ca"];
|
const knownLanguages = ["en", "nl", "de", "fr", "es", "gl", "ca"];
|
||||||
|
|
||||||
|
@ -275,7 +273,20 @@ function transformTranslation(obj: any, path: string[] = [], languageWhitelist :
|
||||||
}
|
}
|
||||||
value = nv;
|
value = nv;
|
||||||
}
|
}
|
||||||
values += `${Utils.Times((_) => " ", path.length + 1)}get ${key}() { return new Translation(${JSON.stringify(value)}, "core:${path.join(".")}.${key}") },
|
|
||||||
|
|
||||||
|
if(value["en"] === undefined){
|
||||||
|
throw `At ${path.join(".")}: Missing 'en' translation for ${JSON.stringify(value)}`
|
||||||
|
}
|
||||||
|
const subParts : string[] = value["en"].match(/{[^}]*}/g)
|
||||||
|
let expr = `return new Translation(${JSON.stringify(value)}, "core:${path.join(".")}.${key}")`
|
||||||
|
if(subParts !== null){
|
||||||
|
// convert '{to_substitute}' into 'to_substitute'
|
||||||
|
const types = Utils.Dedup( subParts.map(tp => tp.substring(1, tp.length - 1)))
|
||||||
|
expr = `return new TypedTranslation<{ ${types.join(", ")} }>(${JSON.stringify(value)}, "core:${path.join(".")}.${key}")`
|
||||||
|
}
|
||||||
|
|
||||||
|
values += `${Utils.Times((_) => " ", path.length + 1)}get ${key}() { ${expr} },
|
||||||
`
|
`
|
||||||
} else {
|
} else {
|
||||||
values += (Utils.Times((_) => " ", path.length + 1)) + key + ": " + transformTranslation(value, [...path, key], languageWhitelist) + ",\n"
|
values += (Utils.Times((_) => " ", path.length + 1)) + key + ": " + transformTranslation(value, [...path, key], languageWhitelist) + ",\n"
|
||||||
|
@ -318,7 +329,7 @@ function genTranslations() {
|
||||||
const translations = JSON.parse(fs.readFileSync("./assets/generated/translations.json", "utf-8"))
|
const translations = JSON.parse(fs.readFileSync("./assets/generated/translations.json", "utf-8"))
|
||||||
const transformed = transformTranslation(translations);
|
const transformed = transformTranslation(translations);
|
||||||
|
|
||||||
let module = `import {Translation} from "../../UI/i18n/Translation"\n\nexport default class CompiledTranslations {\n\n`;
|
let module = `import {Translation, TypedTranslation} from "../../UI/i18n/Translation"\n\nexport default class CompiledTranslations {\n\n`;
|
||||||
module += " public static t = " + transformed;
|
module += " public static t = " + transformed;
|
||||||
module += "\n }"
|
module += "\n }"
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue