| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import Locale from "./Locale" | 
					
						
							|  |  |  | import { Utils } from "../../Utils" | 
					
						
							|  |  |  | import BaseUIElement from "../BaseUIElement" | 
					
						
							|  |  |  | import LinkToWeblate from "../Base/LinkToWeblate" | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  | export class Translation extends BaseUIElement { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public static forcedLanguage = undefined | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-24 16:47:00 +02:00
										 |  |  |     public readonly translations: Record<string, string> | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     context?: string | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-24 16:47:00 +02:00
										 |  |  |     constructor(translations: Record<string, string>, context?: string) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |         super() | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |         if (translations === undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             console.error("Translation without content at " + context) | 
					
						
							| 
									
										
										
										
											2020-11-11 16:23:49 +01:00
										 |  |  |             throw `Translation without content (${context})` | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.context = translations["_context"] ?? context | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |         if (typeof translations === "string") { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             translations = { "*": translations } | 
					
						
							| 
									
										
										
										
											2021-12-21 18:35:31 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         let count = 0 | 
					
						
							| 
									
										
										
										
											2020-11-11 16:23:49 +01:00
										 |  |  |         for (const translationsKey in translations) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             if (!translations.hasOwnProperty(translationsKey)) { | 
					
						
							| 
									
										
										
										
											2021-06-01 21:24:35 +02:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-10-29 03:02:42 +02:00
										 |  |  |             if (translationsKey === "_context" || translationsKey === "_meta") { | 
					
						
							| 
									
										
										
										
											2022-04-06 17:28:51 +02:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             count++ | 
					
						
							|  |  |  |             if (typeof translations[translationsKey] != "string") { | 
					
						
							| 
									
										
										
										
											2021-04-23 17:22:01 +02:00
										 |  |  |                 console.error("Non-string object in translation: ", translations[translationsKey]) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 throw ( | 
					
						
							|  |  |  |                     "Error in an object depicting a translation: a non-string object was found. (" + | 
					
						
							|  |  |  |                     context + | 
					
						
							|  |  |  |                     ")\n    You probably put some other section accidentally in the translation" | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2021-04-10 03:50:44 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-11-11 16:23:49 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.translations = translations | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |         if (count === 0) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             console.error( | 
					
						
							|  |  |  |                 "Constructing a translation, but the object containing translations is empty " + | 
					
						
							|  |  |  |                     context | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2022-03-08 01:05:54 +01:00
										 |  |  |             throw `Constructing a translation, but the object containing translations is empty (${context})` | 
					
						
							| 
									
										
										
										
											2020-11-11 16:23:49 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |     get txt(): string { | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |         return this.textFor(Translation.forcedLanguage ?? Locale.language.data) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public toString() { | 
					
						
							|  |  |  |         return this.txt | 
					
						
							| 
									
										
										
										
											2022-06-05 03:41:53 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     static ExtractAllTranslationsFrom( | 
					
						
							|  |  |  |         object: any, | 
					
						
							|  |  |  |         context = "" | 
					
						
							|  |  |  |     ): { context: string; tr: Translation }[] { | 
					
						
							|  |  |  |         const allTranslations: { context: string; tr: Translation }[] = [] | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |         for (const key in object) { | 
					
						
							|  |  |  |             const v = object[key] | 
					
						
							|  |  |  |             if (v === undefined || v === null) { | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (v instanceof Translation) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 allTranslations.push({ context: context + "." + key, tr: v }) | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (typeof v === "object") { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 allTranslations.push( | 
					
						
							|  |  |  |                     ...Translation.ExtractAllTranslationsFrom(v, context + "." + key) | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return allTranslations | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static fromMap(transl: Map<string, string>) { | 
					
						
							|  |  |  |         const translations = {} | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         let hasTranslation = false | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |         transl?.forEach((value, key) => { | 
					
						
							|  |  |  |             translations[key] = value | 
					
						
							|  |  |  |             hasTranslation = true | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         if (!hasTranslation) { | 
					
						
							|  |  |  |             return undefined | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return new Translation(translations) | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |     Destroy() { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         super.Destroy() | 
					
						
							|  |  |  |         this.isDestroyed = true | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |     public textFor(language: string): string { | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |         if (this.translations["*"]) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return this.translations["*"] | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const txt = this.translations[language] | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |         if (txt !== undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return txt | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const en = this.translations["en"] | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |         if (en !== undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return en | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         for (const i in this.translations) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             if (!this.translations.hasOwnProperty(i)) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return this.translations[i] // Return a random language
 | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         console.error("Missing language ", Locale.language.data, "for", this.translations) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return "" | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-28 03:21:18 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-06-30 03:07:54 +02:00
										 |  |  |      * // Should actually change the content based on the current language
 | 
					
						
							| 
									
										
										
										
											2022-06-28 03:21:18 +02:00
										 |  |  |      * const tr = new Translation({"en":"English", nl: "Nederlands"}) | 
					
						
							|  |  |  |      * Locale.language.setData("en") | 
					
						
							|  |  |  |      * const html = tr.InnerConstructElement() | 
					
						
							|  |  |  |      * html.innerHTML // => "English"
 | 
					
						
							|  |  |  |      * Locale.language.setData("nl") | 
					
						
							|  |  |  |      * html.innerHTML // => "Nederlands"
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-06-30 03:07:54 +02:00
										 |  |  |      * // Should include a link to weblate if context is set
 | 
					
						
							|  |  |  |      * const tr = new Translation({"en":"English"}, "core:test.xyz") | 
					
						
							|  |  |  |      * Locale.language.setData("nl") | 
					
						
							|  |  |  |      * Locale.showLinkToWeblate.setData(true) | 
					
						
							|  |  |  |      * const html = tr.InnerConstructElement() | 
					
						
							|  |  |  |      * html.getElementsByTagName("a")[0].href // => "https://hosted.weblate.org/translate/mapcomplete/core/nl/?offset=1&q=context%3A%3D%22test.xyz%22"
 | 
					
						
							| 
									
										
										
										
											2022-06-28 03:21:18 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |     InnerConstructElement(): HTMLElement { | 
					
						
							|  |  |  |         const el = document.createElement("span") | 
					
						
							| 
									
										
										
										
											2022-01-06 18:51:52 +01:00
										 |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2022-06-30 03:07:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         el.innerHTML = self.txt | 
					
						
							|  |  |  |         if (self.translations["*"] !== undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return el | 
					
						
							| 
									
										
										
										
											2022-06-30 03:07:54 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Locale.language.addCallback((_) => { | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |             if (self.isDestroyed) { | 
					
						
							| 
									
										
										
										
											2022-01-06 18:51:52 +01:00
										 |  |  |                 return true | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-06-28 03:21:18 +02:00
										 |  |  |             el.innerHTML = self.txt | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |         }) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (self.context === undefined || self.context?.indexOf(":") < 0) { | 
					
						
							|  |  |  |             return el | 
					
						
							| 
									
										
										
										
											2022-04-01 12:51:55 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-06-30 03:07:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 12:51:55 +02:00
										 |  |  |         const wrapper = document.createElement("span") | 
					
						
							|  |  |  |         wrapper.appendChild(el) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         Locale.showLinkToWeblate.addCallbackAndRun((doShow) => { | 
					
						
							| 
									
										
										
										
											2022-04-01 12:51:55 +02:00
										 |  |  |             if (!doShow) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2022-04-01 12:51:55 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-01-13 02:48:48 +01:00
										 |  |  |             const linkToWeblate = new LinkToWeblate(self.context, self.translations) | 
					
						
							| 
									
										
										
										
											2022-04-01 12:51:55 +02:00
										 |  |  |             wrapper.appendChild(linkToWeblate.ConstructElement()) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return true | 
					
						
							| 
									
										
										
										
											2022-04-01 12:51:55 +02:00
										 |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return wrapper | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |     public SupportedLanguages(): string[] { | 
					
						
							|  |  |  |         const langs = [] | 
					
						
							|  |  |  |         for (const translationsKey in this.translations) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             if (!this.translations.hasOwnProperty(translationsKey)) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-04-09 02:57:06 +02:00
										 |  |  |             if (translationsKey === "#") { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |             if (!this.translations.hasOwnProperty(translationsKey)) { | 
					
						
							| 
									
										
										
										
											2021-06-08 18:54:29 +02:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |             langs.push(translationsKey) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return langs | 
					
						
							| 
									
										
										
										
											2021-01-14 22:25:11 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public AllValues(): string[] { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return this.SupportedLanguages().map((lng) => this.translations[lng]) | 
					
						
							| 
									
										
										
										
											2021-12-05 02:06:14 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-06-30 03:07:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Constructs a new Translation where every contained string has been modified | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public OnEveryLanguage( | 
					
						
							|  |  |  |         f: (s: string, language: string) => string, | 
					
						
							|  |  |  |         context?: string | 
					
						
							|  |  |  |     ): Translation { | 
					
						
							|  |  |  |         const newTranslations = {} | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  |         for (const lang in this.translations) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             if (!this.translations.hasOwnProperty(lang)) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             newTranslations[lang] = f(this.translations[lang], lang) | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return new Translation(newTranslations, context ?? this.context) | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-15 01:42:38 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Replaces the given string with the given text in the language. | 
					
						
							|  |  |  |      * Other substitutions are left in place | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-03-15 01:42:38 +01:00
										 |  |  |      * const tr = new Translation( | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |      *      {"nl": "Een voorbeeldtekst met {key} en {key1}, en nogmaals {key}", | 
					
						
							| 
									
										
										
										
											2022-03-15 01:42:38 +01:00
										 |  |  |      *      "en": "Just a single {key}"}) | 
					
						
							|  |  |  |      * const r = tr.replace("{key}", "value") | 
					
						
							|  |  |  |      * r.textFor("nl") // => "Een voorbeeldtekst met value en {key1}, en nogmaals value"
 | 
					
						
							|  |  |  |      * r.textFor("en") // => "Just a single value"
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-03-15 01:42:38 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  |     public replace(a: string, b: string) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return this.OnEveryLanguage((str) => str.replace(new RegExp(a, "g"), b)) | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public Clone() { | 
					
						
							| 
									
										
										
										
											2022-04-01 12:51:55 +02:00
										 |  |  |         return new Translation(this.translations, this.context) | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     FirstSentence() { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const tr = {} | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  |         for (const lng in this.translations) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             if (!this.translations.hasOwnProperty(lng)) { | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             let txt = this.translations[lng] | 
					
						
							|  |  |  |             txt = txt.replace(/\..*/, "") | 
					
						
							|  |  |  |             txt = Utils.EllipsesAfter(txt, 255) | 
					
						
							|  |  |  |             tr[lng] = txt | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return new Translation(tr) | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-09 02:57:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-21 02:00:50 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Extracts all images (including HTML-images) from all the embedded translations | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-03-21 02:00:50 +01:00
										 |  |  |      * // should detect sources of <img>
 | 
					
						
							|  |  |  |      * const tr = new Translation({en: "XYZ <img src='a.svg'/> XYZ <img src=\"some image.svg\"></img> XYZ <img src=b.svg/>"}) | 
					
						
							|  |  |  |      * new Set<string>(tr.ExtractImages(false)) // new Set(["a.svg", "b.svg", "some image.svg"])
 | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-04-09 02:57:06 +02:00
										 |  |  |     public ExtractImages(isIcon = false): string[] { | 
					
						
							|  |  |  |         const allIcons: string[] = [] | 
					
						
							|  |  |  |         for (const key in this.translations) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             if (!this.translations.hasOwnProperty(key)) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-04-09 02:57:06 +02:00
										 |  |  |             const render = this.translations[key] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (isIcon) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 const icons = render | 
					
						
							|  |  |  |                     .split(";") | 
					
						
							|  |  |  |                     .filter((part) => part.match(/(\.svg|\.png|\.jpg)$/) != null) | 
					
						
							| 
									
										
										
										
											2021-04-09 02:57:06 +02:00
										 |  |  |                 allIcons.push(...icons) | 
					
						
							| 
									
										
										
										
											2021-04-09 13:59:49 +02:00
										 |  |  |             } else if (!Utils.runningFromConsole) { | 
					
						
							| 
									
										
										
										
											2021-04-09 02:57:06 +02:00
										 |  |  |                 // This might be a tagrendering containing some img as html
 | 
					
						
							|  |  |  |                 const htmlElement = document.createElement("div") | 
					
						
							|  |  |  |                 htmlElement.innerHTML = render | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 const images = Array.from(htmlElement.getElementsByTagName("img")).map( | 
					
						
							|  |  |  |                     (img) => img.src | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2021-04-09 02:57:06 +02:00
										 |  |  |                 allIcons.push(...images) | 
					
						
							| 
									
										
										
										
											2021-04-09 13:59:49 +02:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 // We are running this in ts-node (~= nodejs), and can not access document
 | 
					
						
							|  |  |  |                 // So, we fallback to simple regex
 | 
					
						
							| 
									
										
										
										
											2021-04-10 03:50:44 +02:00
										 |  |  |                 try { | 
					
						
							|  |  |  |                     const matches = render.match(/<img[^>]+>/g) | 
					
						
							|  |  |  |                     if (matches != null) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         const sources = matches | 
					
						
							|  |  |  |                             .map((img) => img.match(/src=("[^"]+"|'[^']+'|[^/ ]+)/)) | 
					
						
							|  |  |  |                             .filter((match) => match != null) | 
					
						
							|  |  |  |                             .map((match) => | 
					
						
							|  |  |  |                                 match[1].trim().replace(/^['"]/, "").replace(/['"]$/, "") | 
					
						
							|  |  |  |                             ) | 
					
						
							| 
									
										
										
										
											2021-04-10 03:50:44 +02:00
										 |  |  |                         allIcons.push(...sources) | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-04-11 19:21:41 +02:00
										 |  |  |                 } catch (e) { | 
					
						
							| 
									
										
										
										
											2021-04-10 03:50:44 +02:00
										 |  |  |                     console.error("Could not search for images: ", render, this.txt) | 
					
						
							|  |  |  |                     throw e | 
					
						
							| 
									
										
										
										
											2021-04-09 13:59:49 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-04-09 02:57:06 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return allIcons.filter((icon) => icon != undefined) | 
					
						
							| 
									
										
										
										
											2021-04-09 02:57:06 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-08 02:36:01 +01:00
										 |  |  |     AsMarkdown(): string { | 
					
						
							|  |  |  |         return this.txt | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-13 01:19:28 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class TypedTranslation<T> extends Translation { | 
					
						
							| 
									
										
										
										
											2022-06-24 16:47:00 +02:00
										 |  |  |     constructor(translations: Record<string, string>, context?: string) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         super(translations, context) | 
					
						
							| 
									
										
										
										
											2022-04-13 01:19:28 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-01 12:51:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-13 01:19:28 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * 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"
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-04-13 01:19:28 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     Subs(text: T, context?: string): Translation { | 
					
						
							| 
									
										
										
										
											2022-05-01 22:58:59 +02:00
										 |  |  |         return this.OnEveryLanguage((template, lang) => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             if (lang === "_context") { | 
					
						
							| 
									
										
										
										
											2022-05-01 22:58:59 +02:00
										 |  |  |                 return template | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return Utils.SubstituteKeys(template, text, lang) | 
					
						
							| 
									
										
										
										
											2022-05-01 22:58:59 +02:00
										 |  |  |         }, context) | 
					
						
							| 
									
										
										
										
											2022-04-13 01:19:28 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-07-25 16:55:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     PartialSubs<X extends string>( | 
					
						
							|  |  |  |         text: Partial<T> & Record<X, string> | 
					
						
							|  |  |  |     ): TypedTranslation<Omit<T, X>> { | 
					
						
							|  |  |  |         const newTranslations: Record<string, string> = {} | 
					
						
							| 
									
										
										
										
											2022-07-25 16:55:44 +02:00
										 |  |  |         for (const lang in this.translations) { | 
					
						
							|  |  |  |             const template = this.translations[lang] | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             if (lang === "_context") { | 
					
						
							|  |  |  |                 newTranslations[lang] = template | 
					
						
							| 
									
										
										
										
											2022-07-25 16:55:44 +02:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             newTranslations[lang] = Utils.SubstituteKeys(template, text, lang) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-25 16:55:44 +02:00
										 |  |  |         return new TypedTranslation<Omit<T, X>>(newTranslations, this.context) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |