mapcomplete/Models/ThemeConfig/Conversion/AddContextToTranslations.ts

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,
}
}
}