The following has evaluated to null or missing:
==> entry.getLocale [in template "42209528364521#278701#301550" at line 254, column 69]
----
Tip: It's the step after the last dot that caused this error, not those before it.
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: #assign alternateURL = "/" + entry.ge... [in template "42209528364521#278701#301550" at line 254, column 41]
----
1<#-- Obtener lista de locales disponibles -->
2<#assign locales = languageUtil.getAvailableLocales(themeDisplay.getScopeGroupId())>
3<#assign loc = ""/>
4<#if request.getSession().getAttribute("LIFERAY_SHARED_LOC")?? >
5 <#assign loc = request.getSession().getAttribute("LIFERAY_SHARED_LOC")/>
6</#if>
7<nav id="nav-principal">
8
9 <div class="menu-mobile-header hidden-desktop">
10 <p id="mobile-menu-title">Menu</p>
11 <button type="button" class="menu-close" aria-label="<@liferay.language key='close-menu' />">
12 <svg aria-hidden="true" class="lexicon-icon lexicon-icon-times" focusable="false" viewBox="0 0 512 512">
13 <path class="lexicon-icon-outline" d="M295.781 256l205.205-205.205c10.998-10.998 10.998-28.814 0-39.781-10.998-10.998-28.815-10.998-39.781 0l-205.205 205.205-205.205-205.238c-10.966-10.998-28.814-10.998-39.781 0-10.998 10.998-10.998 28.814 0 39.781l205.205 205.238-205.205 205.205c-10.998 10.998-10.998 28.815 0 39.781 5.467 5.531 12.671 8.265 19.874 8.265s14.407-2.734 19.907-8.233l205.205-205.238 205.205 205.205c5.5 5.5 12.703 8.233 19.906 8.233s14.407-2.734 19.906-8.233c10.998-10.998 10.998-28.815 0-39.781l-205.238-205.205z"></path>
14 </svg>
15 <span class="hidden-mobile"><@liferay.language key="fixed-horario-cerrar" /></span>
16 </button>
17 </div>
18
19 <ul aria-label="<@liferay.language key="site-pages" />" class="navbar-blank navbar-nav navbar-site">
20 <#assign navItems = entries />
21
22 <#list navItems as navItem>
23 <#assign showChildrenNavItems = (displayDepth != 1) && navItem.hasBrowsableChildren() />
24
25 <#-- Recuperar layout asociado al navItem -->
26 <#assign page = navItem.getLayout() />
27 <#assign hidePage = page.getExpandoBridge().getAttribute("hiddenPageDesktop", false)!false>
28 <#assign nav_item_hide_desktop = hidePage?then("hidden-desktop","")>
29
30 <#assign stringURL = navItem.getURL()>
31 <#assign parts = stringURL?split("$$")>
32
33 <#assign
34 nav_item_attr_has_popup = ""
35 nav_item_caret = ""
36 nav_item_css_class = "lfr-nav-item nav-item"
37 nav_item_link_css_class = "nav-link"
38 nav_item_aria_current = ""
39 nav_item_href_link = 'href=${stringURL?replace("/otrasubicaciones","/otrasubicaciones/"+loc)?replace("/web/", "/")}'
40 />
41
42 <#if parts?size == 2>
43 <#assign urlES = parts[0]>
44 <#assign urlCA = parts[1]>
45
46 <#assign currentLanguageId = themeDisplay.getLanguageId()>
47 <#if currentLanguageId?starts_with("ca")>
48 <#assign nav_item_href_link = "href='${urlCA}'">
49 <#else>
50 <#assign nav_item_href_link = "href='${urlES}'">
51 </#if>
52 </#if>
53
54 <#if navItem.isChildSelected() || navItem.isSelected()>
55 <#assign
56 nav_item_css_class = nav_item_css_class + " selected active"
57 nav_item_aria_current = "aria-current='page'"
58 >
59 </#if>
60
61 <#-- NUEVO: detectar si todos los hijos están hidden-desktop -->
62 <#assign allChildrenHiddenDesktop = true>
63 <#if showChildrenNavItems>
64 <#list navItem.getChildren() as childItem>
65 <#assign pageChild = childItem.getLayout() />
66 <#assign hideChild = pageChild.getExpandoBridge().getAttribute("hiddenPageDesktop", false)!false>
67 <#if !hideChild>
68 <#assign allChildrenHiddenDesktop = false>
69 <#break>
70 </#if>
71 </#list>
72 </#if>
73
74 <#-- CASO 1: tiene hijos visibles -> dropdown normal -->
75 <#if showChildrenNavItems && !allChildrenHiddenDesktop>
76
77 <#assign nav_item_attr_has_popup = "aria-haspopup='true'" />
78 <#assign nav_item_caret>
79 <span class="lfr-nav-child-toggle">
80 <@liferay_aui.icon image="angle-down" markupView="lexicon" />
81 </span>
82 </#assign>
83 <#assign
84 nav_item_css_class = nav_item_css_class + " dropdown"
85 nav_item_link_css_class = nav_item_link_css_class + " dropdown-toggle"
86 />
87
88 <li class="${nav_item_css_class} ${nav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${navItem.getLayoutId()}">
89 <button ${nav_item_attr_has_popup} class="${nav_item_link_css_class}" ${navItem.getTarget()} aria-expanded="false" aria-controls="submenu_${navItem.getLayoutId()}">
90 <@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItem.getName()} ${nav_item_caret}
91 </button>
92
93 <div class="submenu-mobile-header hidden-desktop">
94 <p><@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItem.getName()}</p>
95 <button class="btn-back-menu"><i class="iconcf-photoprev"></i><@liferay.language key="volver" /></button>
96 </div>
97
98 <ul class="child-menu dropdown-menu" id="submenu_${navItem.getLayoutId()}">
99
100 <#-- renderizado de hijos (tu bloque original completo) -->
101 <#list navItem.getChildren() as childItem>
102 <#-- Recuperar layout asociado al childItem -->
103 <#assign pageChild = childItem.getLayout() />
104 <#-- Inicializamos booleano por defecto -->
105 <#assign hideChildPage = pageChild.getExpandoBridge().getAttribute("hiddenPageDesktop", false)>
106 <#assign childnav_item_hide_desktop = "">
107 <#if hideChildPage>
108 <#assign childnav_item_hide_desktop = "hidden-desktop">
109 </#if>
110
111 <#assign stringChildURL = childItem.getURL()>
112 <#assign partsChild = stringChildURL?split("$$")>
113
114 <#assign
115 childnav_item_attr_has_popup = ""
116 childnav_item_caret = ""
117 childnav_item_css_class = "lfr-nav-item nav-item"
118 childnav_item_link_css_class = "nav-link"
119 childnav_item_aria_current = ""
120 childnav_item_href_link = 'href=${stringChildURL?replace("/otrasubicaciones", "/otrasubicaciones/"+loc)?replace("/web/", "/")}'
121 />
122
123 <#if partsChild?size == 2>
124 <#assign urlChildES = partsChild[0]>
125 <#assign urlChildCA = partsChild[1]>
126
127 <#-- Obtener el idioma actual -->
128 <#assign currentLanguageId = themeDisplay.getLanguageId()>
129 <#-- Asignar la URL según el idioma -->
130 <#if currentLanguageId?starts_with("ca")>
131 <#assign childnav_item_href_link = "href='${urlChildCA}'">
132 <#else>
133 <#assign childnav_item_href_link = "href='${urlChildES}'">
134 </#if>
135 <#else>
136 <#assign
137 childnav_item_href_link = 'href=${stringChildURL?replace("/otrasubicaciones", "/otrasubicaciones/"+loc)?replace("/web/", "/")}'
138 />
139 </#if>
140
141 <#if childItem.isChildSelected() || childItem.isSelected()>
142 <#assign
143 childnav_item_css_class = "${childnav_item_css_class} selected active"
144 childnav_item_aria_current = "aria-current='page'"
145 />
146 </#if>
147
148 <#assign showGrandChildren = childItem.hasBrowsableChildren() />
149 <#if showGrandChildren>
150 <#assign childnav_item_css_class = "${childnav_item_css_class} dropdown" />
151 </#if>
152
153 <#if showGrandChildren>
154 <li class="menu-text"><span>${childItem.getName()}</span>
155
156 <ul class="grandchild-menu list-unstyled">
157 <#list childItem.getChildren() as grandChildItem>
158
159 <#assign grandChildPage = grandChildItem.getLayout() />
160 <#assign hideGrandChild = grandChildPage.getExpandoBridge().getAttribute("hiddenPageDesktop", false)>
161 <#assign grandchildnav_item_hide_desktop = "lfr-nav-item nav-item">
162 <#if hideGrandChild>
163 <#assign grandchildnav_item_hide_desktop = "${grandchildnav_item_hide_desktop} hidden-desktop">
164 </#if>
165
166 <#assign stringgrandchildURL = grandChildItem.getURL()>
167 <#assign partsGrandChild = stringgrandchildURL?split("$$")>
168
169 <#if partsChild?size == 2>
170 <#assign urlGrandChildES = partsChild[0]>
171 <#assign urlGrandChildCA = partsChild[1]>
172
173 <#-- Obtener el idioma actual -->
174 <#assign currentLanguageId = themeDisplay.getLanguageId()>
175 <#-- Asignar la URL según el idioma -->
176 <#if currentLanguageId?starts_with("ca")>
177 <#assign grandChild_item_href_link = "href='${urlGrandChildCA}'">
178 <#else>
179 <#assign grandChild_item_href_link = "href='${urlGrandChildES}'">
180 </#if>
181 <#else>
182 <#assign
183 grandChild_item_href_link = 'href=${stringgrandchildURL?replace("/otrasubicaciones", "/otrasubicaciones/"+loc)?replace("/web/", "/")}'
184 />
185 </#if>
186 <#assign grandChild_css_class = "lfr-nav-item nav-item">
187 <#assign grandChild_aria_current = "">
188 <#if grandChildItem.isChildSelected() || grandChildItem.isSelected()>
189 <#assign
190 grandChild_css_class = "${grandChild_css_class} selected active"
191 grandChild_aria_current = "aria-current='page'"
192 />
193 </#if>
194
195 <li class="${grandChild_css_class} ${grandchildnav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${grandChildItem.getLayoutId()}">
196 <a class="nav-link" ${grandChild_item_href_link} ${grandChildItem.getTarget()} ${grandChild_aria_current}>
197 ${grandChildItem.getName()}
198 </a>
199 </li>
200
201 </#list>
202 </ul>
203 <#else>
204 <li class="${childnav_item_css_class} ${childnav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${childItem.getLayoutId()}" role="presentation">
205 <a ${childnav_item_attr_has_popup} class="nav-link ${childnav_item_css_class}" ${childnav_item_href_link} ${childItem.getTarget()} role="menuitem">
206 ${childItem.getName()}
207 </a>
208 </li>
209 </#if>
210 </#list>
211
212 </ul>
213 </li>
214
215 <#-- CASO 2: tiene hijos pero TODOS ocultos → convertir padre en <a> -->
216 <#elseif showChildrenNavItems && allChildrenHiddenDesktop>
217
218 <li class="${nav_item_css_class} ${nav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${navItem.getLayoutId()}">
219 <a class="nav-link" ${nav_item_href_link} ${navItem.getTarget()} ${nav_item_aria_current}>
220 <@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItem.getName()}
221 </a>
222 </li>
223
224 <#-- CASO 3: no tiene hijos -->
225 <#else>
226
227 <li class="${nav_item_css_class} ${nav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${navItem.getLayoutId()}">
228 <a class="${nav_item_link_css_class}" ${nav_item_href_link} ${navItem.getTarget()} ${nav_item_aria_current}>
229 <@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItem.getName()}
230 </a>
231 </li>
232
233 </#if>
234
235 </#list>
236 </ul>
237
238 <#-- Obtener URL actual -->
239 <#assign currentURL = portalUtil.getCurrentURL(renderRequest)>
240 <#assign queryString = "">
241 <#if currentURL?index_of("?") != -1>
242 <#assign queryString = currentURL?substring(currentURL?index_of("?"))>
243 </#if>
244
245 <#-- Obtener canonicalURL para usar con alternateURL -->
246 <#assign canonicalURL = portalUtil.getCanonicalURL(currentURL, themeDisplay, layout, false, false)>
247
248 <#if locales?has_content && (locales?size > 1)>
249 <ul class="custom-mobile-language-portlet hidden-desktop">
250 <#list locales as localeEntry>
251 <#-- Determinar URL alternativo para el idioma -->
252 <#assign alternateURL = portalUtil.getAlternateURL(canonicalURL, themeDisplay, localeEntry, layout)>
253 <#if alternateURL?contains("/ficha")>
254 <#assign alternateURL = "/"+entry.getLocale().getLanguage()>
255 <#else>
256 <#assign alternateURL = alternateURL?replace("/web/guest/","/")>
257 <#assign alternateURL = alternateURL?replace("/web/","/")>
258 </#if>
259
260 <#-- Agregar query string si existe -->
261 <#assign alternateURL = alternateURL + queryString>
262 <#assign labelLanguage = "Castellano">
263 <#if (localeEntry.getLanguage()=="ca")>
264 <#assign labelLanguage = "Català">
265 </#if>
266
267 <#-- Verificar si es el idioma actual -->
268 <#if localeEntry == themeDisplay.getLocale()>
269 <li><span lang="${localeEntry.toLanguageTag()}" class="selected">${labelLanguage}</span></li>
270 <#else>
271 <li><a lang="${localeEntry.toLanguageTag()}" aria-label='<@liferay.language key="change-to-language" /> ${labelLanguage}' href="${alternateURL}">${labelLanguage}</a></li>
272 </#if>
273 </#list>
274 </ul>
275 </#if>
276
277
278</nav>