forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			157 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { DesugaringStep } from "./Conversion"
 | 
						|
import { Utils } from "../../../Utils"
 | 
						|
import Translations from "../../../UI/i18n/Translations"
 | 
						|
 | 
						|
export class AddContextToTranslations<T> extends DesugaringStep<T> {
 | 
						|
    private readonly _prefix: string
 | 
						|
 | 
						|
    constructor(prefix = "") {
 | 
						|
        super(
 | 
						|
            "Adds a '_context' to every object that is probably a translation",
 | 
						|
            ["_context"],
 | 
						|
            "AddContextToTranslation"
 | 
						|
        )
 | 
						|
        this._prefix = prefix
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * const theme = {
 | 
						|
     *   layers: [
 | 
						|
     *       {
 | 
						|
     *           builtin: ["abc"],
 | 
						|
     *           override: {
 | 
						|
     *               title:{
 | 
						|
     *                   en: "Some title"
 | 
						|
     *               }
 | 
						|
     *           }
 | 
						|
     *       }
 | 
						|
     *   ]
 | 
						|
     * }
 | 
						|
     * const rewritten = new AddContextToTranslations<any>("prefix:").convert(theme, "context").result
 | 
						|
     * const expected = {
 | 
						|
     *   layers: [
 | 
						|
     *       {
 | 
						|
     *           builtin: ["abc"],
 | 
						|
     *           override: {
 | 
						|
     *               title:{
 | 
						|
     *                  _context: "prefix:context.layers.0.override.title"
 | 
						|
     *                   en: "Some title"
 | 
						|
     *               }
 | 
						|
     *           }
 | 
						|
     *       }
 | 
						|
     *   ]
 | 
						|
     * }
 | 
						|
     * rewritten // => expected
 | 
						|
     *
 | 
						|
     * // should use the ID if one is present instead of the index
 | 
						|
     * const theme = {
 | 
						|
     *   layers: [
 | 
						|
     *       {
 | 
						|
     *           tagRenderings:[
 | 
						|
     *               {id: "some-tr",
 | 
						|
     *               question:{
 | 
						|
     *                   en:"Question?"
 | 
						|
     *               }
 | 
						|
     *               }
 | 
						|
     *           ]
 | 
						|
     *       }
 | 
						|
     *   ]
 | 
						|
     * }
 | 
						|
     * const rewritten = new AddContextToTranslations<any>("prefix:").convert(theme, "context").result
 | 
						|
     * const expected = {
 | 
						|
     *   layers: [
 | 
						|
     *       {
 | 
						|
     *           tagRenderings:[
 | 
						|
     *               {id: "some-tr",
 | 
						|
     *               question:{
 | 
						|
     *                  _context: "prefix:context.layers.0.tagRenderings.some-tr.question"
 | 
						|
     *                   en:"Question?"
 | 
						|
     *               }
 | 
						|
     *               }
 | 
						|
     *           ]
 | 
						|
     *       }
 | 
						|
     *   ]
 | 
						|
     * }
 | 
						|
     * rewritten // => expected
 | 
						|
     *
 | 
						|
     * // should preserve nulls
 | 
						|
     * const theme = {
 | 
						|
     *   layers: [
 | 
						|
     *       {
 | 
						|
     *           builtin: ["abc"],
 | 
						|
     *           override: {
 | 
						|
     *               name:null
 | 
						|
     *           }
 | 
						|
     *       }
 | 
						|
     *   ]
 | 
						|
     * }
 | 
						|
     * const rewritten = new AddContextToTranslations<any>("prefix:").convert(theme, "context").result
 | 
						|
     * const expected = {
 | 
						|
     *   layers: [
 | 
						|
     *       {
 | 
						|
     *           builtin: ["abc"],
 | 
						|
     *           override: {
 | 
						|
     *               name: null
 | 
						|
     *           }
 | 
						|
     *       }
 | 
						|
     *   ]
 | 
						|
     * }
 | 
						|
     * rewritten // => expected
 | 
						|
     *
 | 
						|
     *
 | 
						|
     * // Should ignore all if '#dont-translate' is set
 | 
						|
     * const theme = {
 | 
						|
     *  "#dont-translate": "*",
 | 
						|
     *   layers: [
 | 
						|
     *       {
 | 
						|
     *           builtin: ["abc"],
 | 
						|
     *           override: {
 | 
						|
     *               title:{
 | 
						|
     *                   en: "Some title"
 | 
						|
     *               }
 | 
						|
     *           }
 | 
						|
     *       }
 | 
						|
     *   ]
 | 
						|
     * }
 | 
						|
     * const rewritten = new AddContextToTranslations<any>("prefix:").convert(theme, "context").result
 | 
						|
     * rewritten // => theme
 | 
						|
     *
 | 
						|
     */
 | 
						|
    convert(
 | 
						|
        json: T,
 | 
						|
        context: string
 | 
						|
    ): { result: T; errors?: string[]; warnings?: string[]; information?: string[] } {
 | 
						|
        if (json["#dont-translate"] === "*") {
 | 
						|
            return { result: json }
 | 
						|
        }
 | 
						|
 | 
						|
        const result = Utils.WalkJson(
 | 
						|
            json,
 | 
						|
            (leaf, path) => {
 | 
						|
                if (leaf === undefined || leaf === null) {
 | 
						|
                    return leaf
 | 
						|
                }
 | 
						|
                if (typeof leaf === "object") {
 | 
						|
                    // follow the path. If we encounter a number, check that there is no ID we can use instead
 | 
						|
                    let breadcrumb = json
 | 
						|
                    for (let i = 0; i < path.length; i++) {
 | 
						|
                        const pointer = path[i]
 | 
						|
                        breadcrumb = breadcrumb[pointer]
 | 
						|
                        if (pointer.match("[0-9]+") && breadcrumb["id"] !== undefined) {
 | 
						|
                            path[i] = breadcrumb["id"]
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    return { ...leaf, _context: this._prefix + context + "." + path.join(".") }
 | 
						|
                } else {
 | 
						|
                    return leaf
 | 
						|
                }
 | 
						|
            },
 | 
						|
            (obj) => obj === undefined || obj === null || Translations.isProbablyATranslation(obj)
 | 
						|
        )
 | 
						|
 | 
						|
        return {
 | 
						|
            result,
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |