In Builder.io in our page and section model for our custom component we want to add a max and min character limit, that we have achieved but we have several locales, how to acheive that for the various locales in our builder registry .
We are not able to get the particular locale for which we need to check.
please see the title field in the following custom component. I am searching for locale in options and context but dont get it
The issue was that the locale wasn’t directly accessible through the standard options or context in the Builder registry. However, the following implementation successfully retrieves the current locale from the Builder state context and applies both minimum and maximum character limits per locale.
Here’s the tested code snippet that works well:
Builder.registerComponent(Heading, {
name: "Heading",
inputs: [
{
name: "text",
type: "string",
defaultValue: "Add a headline",
localized: true,
helperText: "Supports per-locale copy with a 10-120 character range.",
onChange: (options) => {
const currentLocale =
(options.builder &&
options.builder.state &&
options.builder.state.context &&
options.builder.state.context.locale) ||
options.locale;
const value = options.get("text") as
| string
| Record<string, unknown>
| undefined
| null;
const minLength = 4;
const maxLength = 12;
const globalScope =
typeof globalThis === "object" && globalThis !== null
? (globalThis as typeof globalThis & {
alert?: (value: string) => void;
})
: undefined;
const showAlert = (message: string) => {
if (typeof globalScope?.alert === "function") {
globalScope.alert(message);
return;
}
if (typeof alert === "function") {
alert(message);
}
};
if (typeof value === "string") {
if (value.length > maxLength) {
options.set("text", value.slice(0, maxLength));
showAlert(`Maximum length of ${maxLength} reached${currentLocale ? ` for locale ${currentLocale}` : ""}.`);
}
if (value.length !== 0 && value.length < minLength) {
showAlert(
`${currentLocale ? `Locale ${currentLocale}` : "Heading text"} must have at least ${minLength} characters.`,
);
}
return;
}
if (!value || typeof value !== "object") {
return;
}
const mapCandidate = value as unknown as Map<string, unknown>;
const isMapLike =
typeof mapCandidate?.forEach === "function" &&
typeof mapCandidate?.entries === "function";
const entries = isMapLike
? Array.from(mapCandidate.entries())
: Object.entries(value as Record<string, unknown>);
let didModify = false;
entries.forEach(([locale, localeValue]) => {
if (locale.startsWith("@") || typeof localeValue !== "string") {
return;
}
if (localeValue.length > maxLength) {
const truncated = localeValue.slice(0, maxLength);
if (isMapLike) {
mapCandidate.set(locale, truncated);
} else {
(value as Record<string, unknown>)[locale] = truncated;
}
didModify = true;
showAlert(`Maximum length of ${maxLength} reached for locale ${locale}.`);
}
if (localeValue.length !== 0 && localeValue.length < minLength) {
showAlert(`Locale ${locale} must have at least ${minLength} characters.`);
}
});
if (!isMapLike && didModify) {
options.set("text", { ...(value as Record<string, unknown>) });
}
},
},
{
name: "level",
type: "string",
enum: ["h1", "h2", "h3", "h4", "h5", "h6"],
defaultValue: "h2",
},
{
name: "align",
type: "string",
enum: ["left", "center", "right"],
defaultValue: "left",
},
],
});