The following has evaluated to null or missing:
==> entry.getLocale [in template "17415963450886#278197#285544" 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 "17415963450886#278197#285544" at line 254, 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>Menu</p>
11 <button type="button" class="menu-close">
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" role="menubar">
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_href_link = 'href=${stringURL?replace("/otrasubicaciones","/otrasubicaciones/"+loc)?replace("/web/", "/")}'
47 />
48
49 <#if parts?size == 2>
50 <#assign urlES = parts[0]>
51 <#assign urlCA = parts[1]>
52
53 <#assign currentLanguageId = themeDisplay.getLanguageId()>
54 <#if currentLanguageId?starts_with("ca")>
55 <#assign nav_item_href_link = "href='${urlCA}'">
56 <#else>
57 <#assign nav_item_href_link = "href='${urlES}'">
58 </#if>
59 </#if>
60
61 <#if navItem.isChildSelected() || navItem.isSelected()>
62 <#assign nav_item_css_class = nav_item_css_class + " selected active">
63 </#if>
64
65 <#-- NUEVO: detectar si todos los hijos están hidden-desktop -->
66 <#assign allChildrenHiddenDesktop = true>
67 <#if showChildrenNavItems>
68 <#list navItem.getChildren() as childItem>
69 <#assign pageChild = childItem.getLayout() />
70 <#assign hideChild = pageChild.getExpandoBridge().getAttribute("hiddenPageDesktop", false)!false>
71 <#if !hideChild>
72 <#assign allChildrenHiddenDesktop = false>
73 <#break>
74 </#if>
75 </#list>
76 </#if>
77
78 <#-- CASO 1: tiene hijos visibles -> dropdown normal -->
79 <#if showChildrenNavItems && !allChildrenHiddenDesktop>
80
81 <#assign nav_item_attr_has_popup = "aria-haspopup='true'" />
82 <#assign nav_item_caret>
83 <span class="lfr-nav-child-toggle">
84 <@liferay_aui.icon image="angle-down" markupView="lexicon" />
85 </span>
86 </#assign>
87 <#assign
88 nav_item_css_class = nav_item_css_class + " dropdown"
89 nav_item_link_css_class = nav_item_link_css_class + " dropdown-toggle"
90 />
91
92 <li class="${nav_item_css_class} ${nav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${navItem.getLayoutId()}" role="presentation">
93 <button ${nav_item_attr_has_popup} class="${nav_item_link_css_class}" ${navItem.getTarget()} role="menuitem">
94 <@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItemName} ${nav_item_caret}
95 </button>
96
97 <div class="submenu-mobile-header hidden-desktop">
98 <p><@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItemName}</p>
99 <button class="btn-back-menu"><i class="iconcf-photoprev"></i><@liferay.language key="volver" /></button>
100 </div>
101
102 <ul aria-expanded="false" class="child-menu dropdown-menu" role="menu">
103
104 <#-- renderizado de hijos (tu bloque original completo) -->
105 <#list navItem.getChildren() as childItem>
106 <#-- Recuperar layout asociado al childItem -->
107 <#assign pageChild = childItem.getLayout() />
108 <#-- Inicializamos booleano por defecto -->
109 <#assign hideChildPage = pageChild.getExpandoBridge().getAttribute("hiddenPageDesktop", false)>
110 <#assign childnav_item_hide_desktop = "">
111 <#if hideChildPage>
112 <#assign childnav_item_hide_desktop = "hidden-desktop">
113 </#if>
114
115 <#assign stringChildURL = childItem.getURL()>
116 <#assign partsChild = stringChildURL?split("$$")>
117
118 <#assign
119 childnav_item_attr_has_popup = ""
120 childnav_item_caret = ""
121 childnav_item_css_class = "lfr-nav-item nav-item"
122 childnav_item_link_css_class = "nav-link"
123 childnav_item_href_link = 'href=${stringChildURL?replace("/otrasubicaciones", "/otrasubicaciones/"+loc)?replace("/web/", "/")}'
124 />
125
126 <#if partsChild?size == 2>
127 <#assign urlChildES = partsChild[0]>
128 <#assign urlChildCA = partsChild[1]>
129
130 <#-- Obtener el idioma actual -->
131 <#assign currentLanguageId = themeDisplay.getLanguageId()>
132 <#-- Asignar la URL según el idioma -->
133 <#if currentLanguageId?starts_with("ca")>
134 <#assign childnav_item_href_link = "href='${urlChildCA}'">
135 <#else>
136 <#assign childnav_item_href_link = "href='${urlChildES}'">
137 </#if>
138 <#else>
139 <#assign
140 childnav_item_href_link = 'href=${stringChildURL?replace("/otrasubicaciones", "/otrasubicaciones/"+loc)?replace("/web/", "/")}'
141 />
142 </#if>
143
144 <#if childItem.isChildSelected() || childItem.isSelected()>
145 <#assign
146 childnav_item_css_class = "${childnav_item_css_class} selected active"
147 />
148 </#if>
149
150 <#assign showGrandChildren = childItem.hasBrowsableChildren() />
151 <#if showGrandChildren>
152 <#assign childnav_item_css_class = "${childnav_item_css_class} dropdown" />
153 </#if>
154
155 <#if showGrandChildren>
156 <span class="menu-text">${childItem.getName()}</span>
157
158 <ul class="grandchild-menu list-unstyled" role="menu">
159 <#list childItem.getChildren() as grandChildItem>
160
161 <#assign grandChildPage = grandChildItem.getLayout() />
162 <#assign hideGrandChild = grandChildPage.getExpandoBridge().getAttribute("hiddenPageDesktop", false)>
163 <#assign grandchildnav_item_hide_desktop = "lfr-nav-item nav-item">
164 <#if hideGrandChild>
165 <#assign grandchildnav_item_hide_desktop = "${grandchildnav_item_hide_desktop} hidden-desktop">
166 </#if>
167
168 <#assign stringgrandchildURL = grandChildItem.getURL()>
169 <#assign partsGrandChild = stringgrandchildURL?split("$$")>
170
171 <#if partsChild?size == 2>
172 <#assign urlGrandChildES = partsChild[0]>
173 <#assign urlGrandChildCA = partsChild[1]>
174
175 <#-- Obtener el idioma actual -->
176 <#assign currentLanguageId = themeDisplay.getLanguageId()>
177 <#-- Asignar la URL según el idioma -->
178 <#if currentLanguageId?starts_with("ca")>
179 <#assign grandChild_item_href_link = "href='${urlGrandChildCA}'">
180 <#else>
181 <#assign grandChild_item_href_link = "href='${urlGrandChildES}'">
182 </#if>
183 <#else>
184 <#assign
185 grandChild_item_href_link = 'href=${stringgrandchildURL?replace("/otrasubicaciones", "/otrasubicaciones/"+loc)?replace("/web/", "/")}'
186 />
187 </#if>
188 <#assign grandChild_css_class = "lfr-nav-item nav-item">
189 <#if grandChildItem.isChildSelected() || grandChildItem.isSelected()>
190 <#assign
191 grandChild_css_class = "${grandChild_css_class} selected active"
192 />
193 </#if>
194
195 <li class="${grandChild_css_class} ${grandchildnav_item_hide_desktop}" id="layout_${portletDisplay.getId()}_${grandChildItem.getLayoutId()}" role="presentation">
196 <a class="nav-link" ${grandChild_item_href_link} ${grandChildItem.getTarget()} role="menuitem">
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()}" role="presentation">
219 <a class="nav-link" ${nav_item_href_link} ${navItem.getTarget()}>
220 <@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItemName}
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()}" role="presentation">
228 <a class="${nav_item_link_css_class}" ${nav_item_href_link} ${navItem.getTarget()}>
229 <@liferay_theme["layout-icon"] layout=navItem.getLayout() /> ${navItemName}
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 <#assign labelLanguage = "Castellano">
261 <#if (localeEntry.getLanguage()=="ca")>
262 <#assign labelLanguage = "Català">
263 </#if>
264 <#-- Agregar query string si existe -->
265 <#assign alternateURL = alternateURL + queryString>
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</nav>