Liferay: localize layout template names - liferay

I have written a maven module, which contains my custom layout for liferay. The layout works fine but I also want it's name to be translated in a few languages.
Here's my liferay-layout-templates.xml file:
<?xml version="1.0"?>
<!DOCTYPE layout-templates PUBLIC "-//Liferay//DTD Layout Templates 6.2.0//EN" "http://www.liferay.com/dtd/liferay-layout-templates_6_2_0.dtd">
<layout-templates>
<custom>
<layout-template id="2_columns_layout-75_25" name="myLayout">
<template-path>/2_columns_layout-75_25/2_columns_75_25.tpl</template-path>
<wap-template-path>/2_columns_layout-75_25/2_columns_75_25.wap.tpl</wap-template-path>
<thumbnail-path>/2_columns_layout-75_25/2_columns_75_25.png</thumbnail-path>
</layout-template>
</custom>
</layout-templates>
I tried to delete name attribute and add language keys(which were the same to my template id) and values to my hook module, but it didn't work.

At first I was inclined to state that there's no built-in way to localize layout templates. However, I've looked up the JSP in question (in Liferay's html/portlet/layouts_admin/layout/layout_templates_list.jsp) and found the following line (shortened and edited):
<%= HtmlUtil.escape(LanguageUtil.get(locale,
"layout-template-" + layoutTemplateName, layoutTemplateName)) %>
So it looks like the localization keys that you'll need to use for translating your layout-template's name needs to be starting with "layout-template-" followed by the layout template's own name, e.g. given the xml from your question: layout-template-myLayout=My first localized layout template

Related

Liferay 7.3: How to preconfigure a portlet embedded in a page fragment?

We're using Liferay 7.3 (CE) and are trying to embrace the relatively new feature of "Content Pages" with "Page Fragments". We're able to develop page fragments that already include portlets (named "widgets" in the context of content pages), using the <lfr-widget-WIDGETALIAS> tag. So far, that works.
Now we're trying to prepare page fragments that embed portlets with special portlet configuration applied. For example, we want to prepare a page fragment that just shows an asset publisher portlet configured to list WebContent articles from a pre-defined category. The user should be able to just put that fragment onto the page without having to care about the configuration of the asset publisher portlet.
We did not find any direct way to achieve that -- our first guess that the configuration could be written as attributes or content of the <lfr-widget-...> tag was deterred by a hint in the liferay docs that there are no valid attributes or content to attach to that tag.
Does anybody have an inkling of an idea on how to achieve embedding portlets in page fragments with pre-defined portlet configuration applied? (including out-of-the-box Liferay portlets?)
I figured it out myself.
That one thing that the Fragment Editor does not tell you is that the HTML part of a fragment actually is interpreted as a Freemarker template, with the caveat that only Freemarkers alternative syntax is allowed.
That, in turn, means that Liferays taglibs are available, which means we can use the tag <liferay-portlet:runtime> (ported to freemarker alternative syntax, of course), which does accept a defaultPreferences attribute. Now we can just configure the portlet once, find its portletPreferences XML data in the DB (see table PortletPreferences), remove values we do not want to preconfigure and then just use the resulting preferences XML as a value for the defaultPreferences attribute of the <liferay-portlet:runtime> tag.
Care has to be taken for any IDs (e.g. if you want to preconfigure an AssetCategory filter). Better fetch the corresponding object from the corresponding service and get the ID from that object.
This example provides the HTML part for a page fragment that places an AssetPublisher onto the page, preconfigured to show 12 items (instead of the default 20). (CSS, JS and Configuration of the fragment is the default as given by the Page Fragment editor.)
<div class="fragment-12345">
[#assign assetPublisherPortletPreferences="<portlet-preferences>
<preference>
<name>delta</name>
<value>12</value>
</preference>
</portlet-preferences>" /]
[#liferay_portlet["runtime"]
instanceId="${fragmentEntryLinkNamespace}assets"
portletName="com_liferay_asset_publisher_web_portlet_AssetPublisherPortlet"
defaultPreferences="${assetPublisherPortletPreferences}"
/]
</div>
Thank you for this, #orithena. You saved me a lot of trouble.
Another option, to achieve the same result but with simpler syntax, is to use the built-in freeMarkerPortletPreferences:
[#assign assetPublisherPortletPreferences=freeMarkerPortletPreferences.getPreferences({
"delta": "12",
} /]

Druplal view in twig is not rendered

new to drupal.
I have created a view called "my_view_2".
Inside my twig templates I use {{ my_view_2}} to render that view but nothing appears on the page.
If I declare the display of the view as page and assign a node to the view, then the view is rendered. But this way the node template is lost.
The above happens only to some views not very view I have and I can not find the differences between those that working and those that does not working.
any help is appreciated.
Looks like you want to create a view with some kind of display then use twig template to style it. If that's the case, then decide which twig template you want override and copy it over to your /theme folder.
Locate the template you wish to override.
Copy the template file from its base location into your theme folder.
(optionally) Rename the template according to the naming conventions in order to target a more specific subset of areas where the template is used.
Modify the template as you want.
With respect to views look at the below location for which template to copy/override :
core/themes/stable/templates/views/views-view.html.twig).
For example, if we want to override "views-view.html.twig" template for our view, the following template names are valid:
views-view--[viewid]--[view-display-id].html.twig
views-view--[viewid]--page.html.twig
views-view--block.html.twig
views-view--[viewid].html.twig
views-view.html.twig
Once you copy a template file into your theme and clear the cache, Drupal will start using your instance of the template file instead of the base version.
Reference:
Documentation:
https://www.drupal.org/docs/8/theming/twig/twig-template-naming-conventions
https://www.drupal.org/docs/8/theming/twig/working-with-twig-templates

A way access field content with liquid

I am using the latest NuGet version of orchard core. As I want to use Bulma as CSS Framework, I Need to create tepmlates. One of several Problems that I have is: How can I Access the field contents from within a liquid template.
For instance the Blog theme has the content type Article. Within Article there is a field Subtitle. I created the template Article-TextField as
<h2 class="subtitle">{{ Model.Field.Text }}</h2>
The similar .cshtml template works, but apparently with a liquid template, there is no way to Access the TextField Text property. How can I do it the right way?
The problem is that the OrchardCore.ContentFields module doesn't register the TextField type with the Liquid's TemplateContext.GlobalMemberAccessStrategy service, which prevents you from accessing any members on the TextField object.
The module does register DisplayTextFieldViewModel like so:
TemplateContext.GlobalMemberAccessStrategy.Register<DisplayTextFieldViewModel>();
Not only is this unnecessary because the LiquidViewTemplate already registers the model automatically, it also doesn't help you much, since you can only access the model's Field property, but not its Text property.
For example, this will yield some output:
{{ Model }}
This will too:
{{ Model.Field }}
But as you correctly noticed, this won't:
{{ Model.Field.Text }}
This is clearly an omission in Orchard Core, specifically in the ContentFields module.
Since you're using the NuGet packages, you can't hack it into the source code obviously. But what you could do is add a Startup class to your theme that derives from StartupBase and add the following static constructor:
static Startup()
{
TemplateContext.GlobalMemberAccessStrategy.Register<TextField>();
}
Make sure to reference the OrchardCore.ContentFields NuGet package and import the OrchardCore.ContentFields.Fields namespace for your theme to compile.
After that, you will be able to access the Text property from your Liquid template.
Finally, I would recommend that you file an issue on GitHub about this omission so that you can ultimately remove the code I mentioned from your theme's Startup file.

FreeMarker layouts to reduce template redundancy?

According to the FreeMarker include statement docs, you can make header- and footer- aware templates like so:
<#include "/header.ftl">
<!-- Content of my this page -->
<#include "/footer.ftl">
But if my web app has hundreds of pages/views, this is a lot of redundant copy pasta. It would be great if there was like a "layout" concept in FreeMarker, where I could say "Hey, here is a layout:"
<#include "/header.ftl">
<#import_FTL_Somehow>
<#include "/footer.ftl">
And then create separate templates for each view/page (index.ftl, contactUs.ftl, etc.) and then tell FreeMarkers which FTL files "use" the layout. That way I wouldn't have to keep specifying header/footer includes in each and every template file.
Does FreeMarker support this kind of concept?
It doesn't, though if you only need a footer or header it can be solved with some TemplateLoader hack (where the TemplateLoader inserts the header and footer snippets, as if was there in the template file). But the usual solution in FreeMarker is calling the layout code explicitly from each templates, but not with two #include-s directly, but like:
<#my.page>
<!-- Content of my this page -->
</#my.page>
where my is an auto-import (see Configuration.addAutoImport).
Update: Another approach is that you have a layout.ftl like:
Heading stuff here...
<#include bodyTemplate>
Footer stuff here...
And then from Java you always call layout.ftl, but also pass in the body template name using the bodyTemplate variable:
dataModel.put("bodyTemplate", "/foo.ftl");
cfg.getTemplate("layout.ftl").process(dataModel, out);

Disable source parameter on links

Brief description of the default behavior i want to override:
Creating a SharePoint list and using the "Title (linked to Item)" in a view provides a link to the DispForm for that list. By default, this link appends a Source parameter to the URL query string.
I would like to disable this behavior in some way while still retaining the default list view web part that is created by SharePoint when the view is defined.
To be clear, I know how to convert the list-view webpart to XSLT and then control this behavior. If at all possible, I'd like to keep from doing that so that the list view can still be easily supported by Help Desk and also keep the benefits of the standard list view (such as exporting to excel and so forth).
Any ideas?
Thanks in advance for your help.
Troy
SharePoint (2007) dynamically appends the source parameter in a javascript method named GoToLink. That method is defined in SharePoint's core.js file, and it can be easily customized without editing the original file. In fact, you never want to edit that file directly; it will put SharePoint into an "unsupported" state.
We'll create a solution for our customization, so it can easily be deployed or retracted in a consistent manner. Create a new Empty SharePoint solution in Visual Studio, targeted for GAC deployment. Within your project, create the following folder structure:
Templates
Layouts
1033
("1033" is for the English localization; if you're using a different language, your id will be different).
Within "1033", create a new Javascript file (we call our ours "CustomCore.js"). This will contain JUST the code we want to override from Core.js. Since GoToLink is the only thing we're interested in, let's focus on that. Here's the original from Core.js:
function GoToLink(elm) {
if (elm.href==null)
return;
var ch=elm.href.indexOf("?") >=0 ? "&" : "?";
var srcUrl=GetSource();
if (srcUrl !=null && srcUrl !="")
srcUrl=ch+"Source="+srcUrl;
var targetUrl=elm.href+srcUrl;
if (isPortalTemplatePage(targetUrl))
window.top.location=STSPageUrlValidation(targetUrl);
else
window.location=STSPageUrlValidation(targetUrl);
}
Not much to it. For our override, we just need to omit the bits that add the source parameter. From my reckoning, the modified method looks like this:
function GoToLink(elm) {
if (elm.href==null)
return;
if (isPortalTemplatePage(elm.href))
window.top.location=STSPageUrlValidation(elm.href);
else
window.location=STSPageUrlValidation(elm.href);
}
That should be it. Package up the solution and Visual Studio should interpret the "Templates" folder structure correctly when it builds the WSP (look in the generated manifest file for the TemplateFile element and that it's deploying to "Layouts\1033\CustomCore.js").
Once your WSP solution is deployed to SharePoint, we have the final step of referencing it in your Master page. In the HEAD section of your master page, you should see Core.js being referenced like this:
<SharePoint:ScriptLink Language="javascript" runat="server" Defer="True" Name="core.js"/>
We simply add a reference to the new JS file directly beneath this line:
<SharePoint:ScriptLink Language="javascript" runat="server" Defer="True" Name="core.js"/>
<SharePoint:ScriptLink Language="javascript" runat="server" Defer="True" Name="customcore.js"/>
Test it out and make sure it works. Note that this will affect ALL lists on the server to which you've deployed "CustomCore.js" and which use the master page.

Resources