@react-form-builder/core
Version:
React JSON Schema Form Builder to create complex, validated, reusable forms with no deep React knowledge required
314 lines (313 loc) • 10.7 kB
JavaScript
import { makeAutoObservable as h } from "mobx";
import { nameObservable as g } from "../utils/observableNaming.js";
import { isUndefined as u } from "../utils/tools.js";
const f = "LocalizationStore";
class m {
constructor(t, e) {
this.getValue = t, this.getCompatibleId = e;
}
getValue;
getCompatibleId;
initializeLanguageState(t) {
const e = this.getValue();
for (const i of Object.keys(e))
t.add(i), this.#t(i) && delete e[i];
}
getLocalization(t, e, i, o) {
const n = this.getCompatibleId(e), a = this.getCompatibleId(i);
return this.getValue()[t]?.[n]?.[o]?.[a];
}
setLocalization(t, e, i, o, n) {
const a = this.getCompatibleId(e), s = this.getCompatibleId(i);
if (n === "") {
this.#e(t, a, o, s);
return;
}
const r = this.getValue();
r[t] ??= {}, r[t][a] ??= {}, r[t][a][o] ??= {}, r[t][a][o][s] = n;
}
removeLocalization(t, e) {
const i = this.getCompatibleId(t);
for (const o of e) {
const n = this.getValue()[o];
n && (delete n[i], Object.keys(n).length === 0 && delete this.getValue()[o]);
}
}
removeLocalizationForType(t, e, i) {
const o = this.getCompatibleId(t);
for (const n of i) {
const a = this.getValue()[n];
a?.[o] && (delete a[o][e], Object.keys(a[o]).length === 0 && delete a[o], Object.keys(a).length === 0 && delete this.getValue()[n]);
}
}
hasLocalization(t, e, i) {
const o = this.getCompatibleId(t), n = this.getCompatibleId(e);
return Object.values(this.getValue()).some((a) => !u(a?.[o]?.[i]?.[n]));
}
getLocalizationForComponent(t, e) {
const i = this.getCompatibleId(t), o = {};
for (const n of e) {
const a = this.getValue()[n];
if (!a) continue;
const s = a[i];
s && (o[n] = {}, o[n][t] = s);
}
return o;
}
addLocalizationWithNewKey(t, e, i) {
const o = this.getCompatibleId(i), n = Object.keys(t);
for (const a of n) {
const s = t[a][e];
if (!s) continue;
const r = this.getValue();
r[a] ??= {}, r[a][o] = s;
}
}
changeComponentKey(t, e, i) {
const o = this.getCompatibleId(t), n = this.getCompatibleId(e);
for (const a of i) {
const s = this.getValue()[a];
if (!s) continue;
const r = s[o];
r && (s[n] = r, delete s[o]);
}
}
#e(t, e, i, o) {
const n = this.getValue(), a = n[t], s = a?.[e], r = s?.[i];
!r || !Object.prototype.hasOwnProperty.call(r, o) || (delete r[o], Object.keys(r).length === 0 && delete s[i], s && Object.keys(s).length === 0 && delete a[e], a && Object.keys(a).length === 0 && delete n[t]);
}
#t(t) {
const e = this.getValue()[t];
return !!e && Object.keys(e).length === 0;
}
}
class L {
constructor(t, e, i) {
this.configuredLanguageCodes = t, this.hasTranslations = e, this.withTranslationsLanguageKeys = i;
}
configuredLanguageCodes;
hasTranslations;
withTranslationsLanguageKeys;
findLocalizationKey(t) {
const {
exactConfigured: e,
exactWithTranslations: i,
sameCodeConfigured: o,
sameCodeWithTranslations: n
} = this.#n(t);
return i || n || e || o || null;
}
hasLanguage(t) {
return this.#e(t) !== null;
}
#e(t) {
const { exactConfigured: e, sameCodeConfigured: i } = this.#n(t);
return e ?? i ?? null;
}
#t(t) {
return this.hasTranslations(t) ? t : null;
}
#i(t) {
return this.hasTranslations(t) || this.configuredLanguageCodes.has(t) ? t : null;
}
#o(t, e) {
const [i] = t.split("-");
for (const o of this.withTranslationsLanguageKeys())
if (o.startsWith(`${i}-`) && (!e || this.hasTranslations(o)))
return o;
return null;
}
#n(t) {
const e = this.#i(t), i = this.#o(t, !1) ?? this.#a(t), o = this.#t(t), n = this.#o(t, !0);
return {
exactConfigured: e,
sameCodeConfigured: i,
exactWithTranslations: o,
sameCodeWithTranslations: n
};
}
#a(t) {
const [e] = t.split("-");
for (const i of this.configuredLanguageCodes)
if (i.startsWith(`${e}-`)) return i;
return null;
}
}
class p {
constructor(t, e) {
this.languageFullCode = t, this.localizationStore = e, h(this, void 0, { name: g("LocalizationObservable") });
}
languageFullCode;
localizationStore;
get items() {
const t = this.localizationStore.findLocalizationKey(this.languageFullCode), e = t ? this.localizationStore.value[t] : null, { engine: i } = this.localizationStore;
if (e) {
const o = this.#e(e), n = i.addMessages(this.languageFullCode, o);
return n.length !== 0 ? (console.error(`Unable to add localization resource: ${n}`), null) : o;
}
return null;
}
#e(t) {
const e = {}, { engine: i } = this.localizationStore;
return Object.entries(t).forEach(([o, n]) => {
Object.entries(n ?? {}).forEach(([a, s]) => {
Object.entries(s ?? {}).forEach(([r, l]) => {
if (!u(l) && l !== null) {
const d = `${i.getCompatibleId(o)}_${a}_${i.getCompatibleId(r)}`;
e[d] = l;
}
});
});
}), e;
}
}
class C {
/**
* Creates a new LocalizationStore instance.
* @param value the initial localization value.
* @param engine the localization engine to use.
*/
constructor(t = {}, e) {
this.value = t, this.engine = e, this.repository = new m(() => this.value, this.engine.getCompatibleId.bind(this.engine)), this.resolver = new L(
this.configuredLanguageCodes,
this.#i.bind(this),
() => Object.keys(this.value)
), this.#e(), h(this, void 0, { name: g(f) });
}
value;
engine;
localizationCache = /* @__PURE__ */ new Map();
configuredLanguageCodes = /* @__PURE__ */ new Set();
repository;
resolver;
#e() {
this.repository.initializeLanguageState(this.configuredLanguageCodes);
}
#t() {
this.localizationCache.clear();
}
/**
* Returns value of localization constant.
* @param languageFullCode the full code (en-US, en-GB etc.) of the language we are looking to localize.
* @param componentKey the component we are looking to localize.
* @param propertyName the property name we are looking to localize.
* @param type the type of localization.
* @returns the value of localization constant.
*/
getLocalization(t, e, i, o) {
const n = this.findLocalizationKey(t) ?? t;
return this.repository.getLocalization(n, e, i, o);
}
/**
* Returns normalized localization item id for the component property.
* @param componentKey the component key.
* @param propertyName the component property name.
* @returns normalized localization item id.
*/
getLocalizationItemId(t, e) {
return this.engine.getCompatibleId(`${t}_${e}`);
}
/**
* Sets localization for component property.
* @param languageFullCode the full code (en-US, en-GB etc.) of the language in which localization will be set.
* @param componentKey the component key that requires localization.
* @param propertyName the component's property name to be localized.
* @param type the type of localization.
* @param value the localization value to persist.
*/
setLocalization(t, e, i, o, n) {
this.repository.setLocalization(t, e, i, o, n), this.#t();
}
/**
* Removes localization for component.
* @param componentKey the component key that requires localization removal.
*/
removeLocalization(t) {
this.repository.removeLocalization(t, this.langCodes), this.#t();
}
/**
* Removes localization for component with specified type.
* @param componentKey the component key that requires localization removal.
* @param type the localization type.
*/
removeLocalizationForType(t, e) {
this.repository.removeLocalizationForType(t, e, this.langCodes), this.#t();
}
/**
* Checks that the specified language exists in the localization.
* Looks for exact match first, then match by language code only.
* @param languageFullCode The full code (en-US, en-GB etc.) of the language to be checked.
* @returns true if the specified language exists in the localization.
*/
hasLanguage(t) {
return this.resolver.hasLanguage(t);
}
/**
* Checks that the specified property has localization.
* @param componentKey the component we are looking to localize.
* @param propertyName the component's property name to be localized.
* @param type the type of localization.
* @returns true if the specified property has localization in at least one language.
*/
hasLocalization(t, e, i) {
return this.repository.hasLocalization(t, e, i);
}
/**
* Finds the best matching localization key for the given language code.
* Looks for exact match first, then match by language code only.
* @param languageFullCode the requested language full code.
* @returns the best matching language full code or null if no match found.
*/
findLocalizationKey(t) {
return this.resolver.findLocalizationKey(t);
}
#i(t) {
const e = this.value[t];
return !!e && Object.keys(e).length > 0;
}
/**
* @inheritDoc
*/
getItems(t) {
const e = this.localizationCache.get(t) ?? new p(t, this);
return this.localizationCache.has(t) || this.localizationCache.set(t, e), e.items;
}
/**
* Changes the component key for all languages in the value object.
* @param oldComponentKey the old component key to be replaced.
* @param newComponentKey the new component key to replace the old component key.
*/
changeComponentKey(t, e) {
this.repository.changeComponentKey(t, e, this.langCodes), this.#t();
}
/**
* Retrieves the localization values for a given component key.
* @param componentKey the key of the component to retrieve localization for.
* @returns the object containing the localization values for the component in each supported language.
*/
getLocalizationForComponent(t) {
return this.repository.getLocalizationForComponent(t, this.langCodes);
}
/**
* Inserts the localization values for a given component key. Replaces the old component key with the new component key.
* @param localization the localization object for insertion.
* @param oldComponentKey the old component key that needs to be replaced.
* @param newComponentKey the new component key to be added.
*/
addLocalizationWithNewKey(t, e, i) {
this.repository.addLocalizationWithNewKey(t, e, i), this.#t();
}
/**
* @returns the available language codes.
*/
get langCodes() {
return [.../* @__PURE__ */ new Set([
...Object.keys(this.value),
...this.configuredLanguageCodes
])];
}
}
export {
C as LocalizationStore
};
//# sourceMappingURL=LocalizationStore.js.map