forked from MapComplete/MapComplete
Add translation buttons
This commit is contained in:
parent
592bc4ae0b
commit
2c7fb556dc
31 changed files with 442 additions and 150 deletions
|
@ -1,15 +1,21 @@
|
|||
import Locale from "./Locale";
|
||||
import {Utils} from "../../Utils";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import Link from "../Base/Link";
|
||||
import Svg from "../../Svg";
|
||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
import LinkToWeblate from "../Base/LinkToWeblate";
|
||||
|
||||
export class Translation extends BaseUIElement {
|
||||
|
||||
public static forcedLanguage = undefined;
|
||||
|
||||
public readonly translations: object
|
||||
context?: string;
|
||||
|
||||
constructor(translations: object, context?: string) {
|
||||
super()
|
||||
this.context = context;
|
||||
if (translations === undefined) {
|
||||
console.error("Translation without content at "+context)
|
||||
throw `Translation without content (${context})`
|
||||
|
@ -101,13 +107,35 @@ export class Translation extends BaseUIElement {
|
|||
InnerConstructElement(): HTMLElement {
|
||||
const el = document.createElement("span")
|
||||
const self = this
|
||||
|
||||
|
||||
Locale.language.addCallbackAndRun(_ => {
|
||||
if (self.isDestroyed) {
|
||||
return true
|
||||
}
|
||||
el.innerHTML = this.txt
|
||||
})
|
||||
return el;
|
||||
|
||||
if (self.translations["*"] !== undefined || self.context === undefined || self.context?.indexOf(":") < 0) {
|
||||
return el;
|
||||
}
|
||||
|
||||
const linkToWeblate = new LinkToWeblate(self.context, self.translations)
|
||||
|
||||
const wrapper = document.createElement("span")
|
||||
wrapper.appendChild(el)
|
||||
wrapper.classList.add("flex")
|
||||
Locale.showLinkToWeblate.addCallbackAndRun(doShow => {
|
||||
|
||||
if (!doShow) {
|
||||
return;
|
||||
}
|
||||
wrapper.appendChild(linkToWeblate.ConstructElement())
|
||||
return true;
|
||||
})
|
||||
|
||||
|
||||
return wrapper ;
|
||||
}
|
||||
|
||||
public SupportedLanguages(): string[] {
|
||||
|
@ -131,11 +159,25 @@ export class Translation extends BaseUIElement {
|
|||
return this.SupportedLanguages().map(lng => this.translations[lng]);
|
||||
}
|
||||
|
||||
public Subs(text: any): Translation {
|
||||
return this.OnEveryLanguage((template, lang) => Utils.SubstituteKeys(template, text, lang))
|
||||
/**
|
||||
* 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): Translation {
|
||||
public OnEveryLanguage(f: (s: string, language: string) => string, context?: string): Translation {
|
||||
const newTranslations = {};
|
||||
for (const lang in this.translations) {
|
||||
if (!this.translations.hasOwnProperty(lang)) {
|
||||
|
@ -143,37 +185,10 @@ export class Translation extends BaseUIElement {
|
|||
}
|
||||
newTranslations[lang] = f(this.translations[lang], lang);
|
||||
}
|
||||
return new Translation(newTranslations);
|
||||
return new Translation(newTranslations, context ?? this.context);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Given a translation such as `{en: "How much of bicycle_types are rented here}` (which is this translation)
|
||||
* and a translation object `{ en: "electrical bikes" }`, plus the translation specification `bicycle_types`, will return
|
||||
* a new translation:
|
||||
* `{en: "How much electrical bikes are rented here?"}`
|
||||
*
|
||||
* @param translationObject
|
||||
* @param stringToReplace
|
||||
* @constructor
|
||||
*/
|
||||
public Fuse(translationObject: Translation, stringToReplace: string): Translation{
|
||||
const translations = this.translations
|
||||
const newTranslations = {}
|
||||
for (const lang in translations) {
|
||||
const target = translationObject.textFor(lang)
|
||||
if(target === undefined){
|
||||
continue
|
||||
}
|
||||
if(typeof target !== "string"){
|
||||
throw "Invalid object in Translation.fuse: translationObject['"+lang+"'] is not a string, it is: "+JSON.stringify(target)
|
||||
}
|
||||
newTranslations[lang] = this.translations[lang].replaceAll(stringToReplace, target)
|
||||
}
|
||||
return new Translation(newTranslations)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces the given string with the given text in the language.
|
||||
* Other substitutions are left in place
|
||||
|
@ -190,7 +205,7 @@ export class Translation extends BaseUIElement {
|
|||
}
|
||||
|
||||
public Clone() {
|
||||
return new Translation(this.translations)
|
||||
return new Translation(this.translations, this.context)
|
||||
}
|
||||
|
||||
FirstSentence() {
|
||||
|
@ -256,4 +271,6 @@ export class Translation extends BaseUIElement {
|
|||
AsMarkdown(): string {
|
||||
return this.txt
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue