Todos los textos de mi aplicación están dentro de un archivo .json para fines de traducción. Necesito una función para obtener el texto correspondiente según el idioma seleccionado.
Creo que debería ser una tarea fácil, pero no veo la solución.
Tengo el siguiente objeto:
{ section1: { btn: { en: "English", es: "Español" }, title: { en: "Web Frontend Developer", es: "Desarrollador Web de Frontend" }, card: { title: { en: "Hello!", es: "Hola!" }, btn: { en: "Get started", es: "Empecemos" }, } } } Este objeto debe pasarse a una función como primer parámetro y el segundo parámetro debe ser el idioma (en este caso "en" o "es"). Quiero algo como esto: filterObjByLanguage(obj, "es")
Y debería devolver:
{ section1: { btn: "Español", title: "Desarrollador Web de Frontend", card: { title: "Hola!", btn: "Empecemos" } } } Básicamente, recorre cada parte del objeto y donde hay un { en:"text", es: "texto" } , elige uno de ellos en función del segundo parámetro.
Este es mi intento, pero solo la primera capa del objeto se devuelve correctamente, el resto no está definido.
const filterObjByLanguage= (obj: any, lang: string): any => { const output = Object.assign(obj, {}); const loop = (obj: any, isRoot: boolean = true): any => { for (var k in obj) { const value = output[k]; const valueAtSelected = value?.[lang]; if (typeof value === "string") { continue; } else if (valueAtSelected) { if (isRoot) output[k] = valueAtSelected; else return valueAtSelected; } else { if (isRoot) output[k] = loop(value, false); else return loop(value, false); } } }; loop(output); return output; };Aquí hay una dificultad: saber qué objetos son valores de lenguaje versus cuáles son colecciones de ellos. En esta solución, utilizo la existencia de una propiedad 'en' como señal. Una vez que tenemos eso, se trata principalmente de desarmar y reconstruir objetos usando Object.entries y Object.fromEntries . En JS simple (¡dejaré Typescript para aquellos que lo aprecian!), Podría verse así:
const filterObjByLanguage = (lang) => (o) => Object (o) === o ? 'en' in o ? o [lang] || '' : Object .fromEntries ( Object .entries (o) .map (([k, v]) => [k, filterObjByLanguage (lang) (v)]) ) : o const i18n = {section1: {btn: {en: "English", es: "Español"}, title: {en: "Web Frontend Developer", es: "Desarrollador Web de Frontend"}, card: {title: {en: "Hello!", es: "Hola!"}, btn: {en: "Get started", es: "Empecemos"}}}} console .log ('English', filterObjByLanguage ('en') (i18n)) console .log ('Español', filterObjByLanguage ('es') (i18n)) console .log ('Français', filterObjByLanguage ('fr') (i18n)) .as-console-wrapper {max-height: 100% !important; top: 0} Esto también toma la decisión de que los valores de idioma que faltan son simplemente cadenas vacías. Si prefiere undefined , puede simplemente eliminar || '' . Podemos extender esto a matrices si es necesario con una simple modificación:
const filterObjByLanguage = (lang) => (o) => Array .isArray (o) ? o .map (filterObjByLanguage (lang)) : Object (o) === o ? 'en' in o ? o [lang] || '' : Object .fromEntries ( Object .entries (o) .map (([k, v]) => [k, filterObjByLanguage (lang) (v)]) ) : o