The following has evaluated to null or missing:
==> entry.getLocale [in template "17415963450886#278197#285544" at line 267, 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 "17415963450886#278197#285544" at line 267, column 41]
----
1<#-- Obtener lista de locales disponibles -->
2<#assign locales = languageUtil.getAvailableLocales()>
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 navItemName = navItem.getName() />
24 <#-- Caso menu de Macaya -->
25 <#if navItemName?contains("Convocatoria")>
26 <#assign navItemName = "Convocatoria"/>
27 </#if>
28 <#if navItemName?contains("Convocatòria")>
29 <#assign navItemName = "Convocatòria"/>
30 </#if>
31 <#assign showChildrenNavItems = (displayDepth != 1) && navItem.hasBrowsableChildren() />
32
33 <#-- Recuperar layout asociado al navItem -->
34 <#assign page = navItem.getLayout() />
35 <#assign hidePage = page.getExpandoBridge().getAttribute("hiddenPageDesktop", false)!false>
36 <#assign nav_item_hide_desktop = hidePage?then("hidden-desktop","")>
37
38 <#assign stringURL = navItem.getURL()>
39 <#assign parts = stringURL?split("$$")>
40
41 <#assign
42 nav_item_attr_has_popup = ""
43 nav_item_caret = ""
44 nav_item_css_class = "lfr-nav-item nav-item"
45 nav_item_link_css_class = "nav-link"
46 nav_item_aria_current = ""
47 nav_item_href_link = 'href=${stringURL?replace("/otrasubicaciones","/otrasubicaciones/"+loc)?replace("/web/", "/")}'
48 />
49
50 <#if parts?size == 2>
51 <#assign urlES = parts[0]>
52 <#assign urlCA = parts[1]>
53
54 <#assign currentLanguageId = themeDisplay.getLanguageId()>
55 <#if currentLanguageId?starts_with("ca")>
56 <#assign nav_item_href_link = "href='${urlCA}'">
57 <#else>
58 <#assign nav_item_href_link = "href='${urlES}'">
59 </#if>
60 </#if>
61
62 <#if navItem.isChildSelected() || navItem.isSelected()>
63 <#assign
64 nav_item_css_class = nav_item_css_class + " selected active"
65 nav_item_aria_current = "aria-current='page'"
66 >
67 </#if>
68
69 <#-- NUEVO: detectar si todos los hijos están hidden-desktop -->
70 <#assign allChildrenHiddenDesktop = true>
71 <#if showChildrenNavItems>
72 <#list navItem.getChildren() as childItem>
73 <#assign pageChild = childItem.getLayout() />
74 <#assign hideChild = pageChild.getExpandoBridge().getAttribute("hiddenPageDesktop", false)!false>
75 <#if !hideChild>
76 <#assign allChildrenHiddenDesktop = false>
77 <#break>
78 </#if>
79 </#list>
80 </#if>
81
82 <#-- CASO 1: tiene hijos visibles -> dropdown normal -->
83 <#if showChildrenNavItems && !allChildrenHiddenDesktop>
84
85 <#assign nav_item_attr_has_popup = "aria-haspopup='true'" />
86 <#assign nav_item_caret>
87 <span class="lfr-nav-child-toggle">
88 <@liferay_aui.icon image="angle-down" markupView="lexicon" />
89 </span>
90 </#assign>
91 <#assign
92 nav_item_css_class = nav_item_css_class + " dropdown"
93 nav_item_link_css_class = nav_item_link_css_class + " dropdown-toggle"
94 />
95
96 <li class="${nav_item_css_class} ${nav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${navItem.getLayoutId()}">
97 <button ${nav_item_attr_has_popup} class="${nav_item_link_css_class}" ${navItem.getTarget()} aria-expanded="false" aria-controls="submenu_${navItem.getLayoutId()}">
98 <@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItemName} ${nav_item_caret}
99 </button>
100
101 <div class="submenu-mobile-header hidden-desktop">
102 <p><@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItemName}</p>
103 <button class="btn-back-menu"><i class="iconcf-photoprev"></i><@liferay.language key="volver" /></button>
104 </div>
105
106 <ul class="child-menu dropdown-menu" id="submenu_${navItem.getLayoutId()}">
107
108 <#-- renderizado de hijos (tu bloque original completo) -->
109 <#list navItem.getChildren() as childItem>
110 <#-- Recuperar layout asociado al childItem -->
111 <#assign pageChild = childItem.getLayout() />
112 <#-- Inicializamos booleano por defecto -->
113 <#assign hideChildPage = pageChild.getExpandoBridge().getAttribute("hiddenPageDesktop", false)>
114 <#assign childnav_item_hide_desktop = "">
115 <#if hideChildPage>
116 <#assign childnav_item_hide_desktop = "hidden-desktop">
117 </#if>
118
119 <#assign stringChildURL = childItem.getURL()>
120 <#assign partsChild = stringChildURL?split("$$")>
121
122 <#assign
123 childnav_item_attr_has_popup = ""
124 childnav_item_caret = ""
125 childnav_item_css_class = "lfr-nav-item nav-item"
126 childnav_item_link_css_class = "nav-link"
127 childnav_item_aria_current = ""
128 childnav_item_href_link = 'href=${stringChildURL?replace("/otrasubicaciones", "/otrasubicaciones/"+loc)?replace("/web/", "/")}'
129 />
130
131 <#if partsChild?size == 2>
132 <#assign urlChildES = partsChild[0]>
133 <#assign urlChildCA = partsChild[1]>
134
135 <#-- Obtener el idioma actual -->
136 <#assign currentLanguageId = themeDisplay.getLanguageId()>
137 <#-- Asignar la URL según el idioma -->
138 <#if currentLanguageId?starts_with("ca")>
139 <#assign childnav_item_href_link = "href='${urlChildCA}'">
140 <#else>
141 <#assign childnav_item_href_link = "href='${urlChildES}'">
142 </#if>
143 <#else>
144 <#assign
145 childnav_item_href_link = 'href=${stringChildURL?replace("/otrasubicaciones", "/otrasubicaciones/"+loc)?replace("/web/", "/")}'
146 />
147 </#if>
148
149 <#if childItem.isChildSelected() || childItem.isSelected()>
150 <#assign
151 childnav_item_css_class = "${childnav_item_css_class} selected active"
152 childnav_item_aria_current = "aria-current='page'"
153 />
154 </#if>
155
156 <#assign showGrandChildren = childItem.hasBrowsableChildren() />
157 <#if showGrandChildren>
158 <#assign childnav_item_css_class = "${childnav_item_css_class} dropdown" />
159 </#if>
160
161 <#if showGrandChildren>
162 <li class="menu-text"><span>${childItem.getName()}</span>
163
164 <ul class="grandchild-menu list-unstyled">
165 <#list childItem.getChildren() as grandChildItem>
166
167 <#assign grandChildPage = grandChildItem.getLayout() />
168 <#assign hideGrandChild = grandChildPage.getExpandoBridge().getAttribute("hiddenPageDesktop", false)>
169 <#assign grandchildnav_item_hide_desktop = "lfr-nav-item nav-item">
170 <#if hideGrandChild>
171 <#assign grandchildnav_item_hide_desktop = "${grandchildnav_item_hide_desktop} hidden-desktop">
172 </#if>
173
174 <#assign stringgrandchildURL = grandChildItem.getURL()>
175 <#assign partsGrandChild = stringgrandchildURL?split("$$")>
176
177 <#if partsChild?size == 2>
178 <#assign urlGrandChildES = partsChild[0]>
179 <#assign urlGrandChildCA = partsChild[1]>
180
181 <#-- Obtener el idioma actual -->
182 <#assign currentLanguageId = themeDisplay.getLanguageId()>
183 <#-- Asignar la URL según el idioma -->
184 <#if currentLanguageId?starts_with("ca")>
185 <#assign grandChild_item_href_link = "href='${urlGrandChildCA}'">
186 <#else>
187 <#assign grandChild_item_href_link = "href='${urlGrandChildES}'">
188 </#if>
189 <#else>
190 <#assign
191 grandChild_item_href_link = 'href=${stringgrandchildURL?replace("/otrasubicaciones", "/otrasubicaciones/"+loc)?replace("/web/", "/")}'
192 />
193 </#if>
194 <#assign grandChild_css_class = "lfr-nav-item nav-item">
195 <#assign grandChild_aria_current = "">
196 <#if grandChildItem.isChildSelected() || grandChildItem.isSelected()>
197 <#assign
198 grandChild_css_class = "${grandChild_css_class} selected active"
199 grandChild_aria_current = "aria-current='page'"
200 />
201 </#if>
202
203 <li class="${grandChild_css_class} ${grandchildnav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${grandChildItem.getLayoutId()}">
204 <a class="nav-link" ${grandChild_item_href_link} ${grandChildItem.getTarget()} ${grandChild_aria_current}>
205 ${grandChildItem.getName()}
206 </a>
207 </li>
208
209 </#list>
210 </ul>
211 </li>
212 <#else>
213 <#-- Caso menu de Macaya -->
214
215 <#assign childItemName = childItem.getName()?replace("^(Convocatoria|Convocatòria).*?(\\d{4}(?:-\\d{4})?)$", "$1 $2", "r")/>
216
217 <li class="${childnav_item_css_class} ${childnav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${childItem.getLayoutId()}" role="presentation">
218 <a ${childnav_item_attr_has_popup} class="nav-link ${childnav_item_css_class}" ${childnav_item_href_link} ${childItem.getTarget()} role="menuitem">
219 ${childItemName}
220 </a>
221 </li>
222 </#if>
223 </#list>
224
225 </ul>
226 </li>
227
228 <#-- CASO 2: tiene hijos pero TODOS ocultos → convertir padre en <a> -->
229 <#elseif showChildrenNavItems && allChildrenHiddenDesktop>
230
231 <li class="${nav_item_css_class} ${nav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${navItem.getLayoutId()}">
232 <a class="nav-link" ${nav_item_href_link} ${navItem.getTarget()} ${nav_item_aria_current}>
233 <@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItemName}
234 </a>
235 </li>
236
237 <#-- CASO 3: no tiene hijos -->
238 <#else>
239
240 <li class="${nav_item_css_class} ${nav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${navItem.getLayoutId()}">
241 <a class="${nav_item_link_css_class}" ${nav_item_href_link} ${navItem.getTarget()} ${nav_item_aria_current}>
242 <@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItemName}
243 </a>
244 </li>
245
246 </#if>
247
248 </#list>
249 </ul>
250
251 <#-- Obtener URL actual -->
252 <#assign currentURL = portalUtil.getCurrentURL(renderRequest)>
253 <#assign queryString = "">
254 <#if currentURL?index_of("?") != -1>
255 <#assign queryString = currentURL?substring(currentURL?index_of("?"))>
256 </#if>
257
258 <#-- Obtener canonicalURL para usar con alternateURL -->
259 <#assign canonicalURL = portalUtil.getCanonicalURL(currentURL, themeDisplay, layout, false, false)>
260
261 <#if locales?has_content && (locales?size > 1)>
262 <ul class="custom-mobile-language-portlet hidden-desktop">
263 <#list locales as localeEntry>
264 <#-- Determinar URL alternativo para el idioma -->
265 <#assign alternateURL = portalUtil.getAlternateURL(canonicalURL, themeDisplay, localeEntry, layout)>
266 <#if alternateURL?contains("/ficha")>
267 <#assign alternateURL = "/"+entry.getLocale().getLanguage()>
268 <#else>
269 <#assign alternateURL = alternateURL?replace("/web/guest/","/")>
270 <#assign alternateURL = alternateURL?replace("/web/","/")>
271 </#if>
272
273 <#assign labelLanguage = "Castellano">
274 <#if (localeEntry.getLanguage()=="ca")>
275 <#assign labelLanguage = "Català">
276 </#if>
277 <#-- Agregar query string si existe -->
278 <#assign alternateURL = alternateURL + queryString>
279
280 <#-- Verificar si es el idioma actual -->
281 <#if localeEntry == themeDisplay.getLocale()>
282 <li><span lang="${localeEntry.toLanguageTag()}" class="selected">${labelLanguage}</span></li>
283 <#else>
284 <li><a lang="${localeEntry.toLanguageTag()}" aria-label='<@liferay.language key="change-to-language" /> ${labelLanguage}' href="${alternateURL}">${labelLanguage}</a></li>
285 </#if>
286 </#list>
287 </ul>
288 </#if>
289
290</nav>