Sep 18 2019
Sep 18
many different people profile heads in different colors

Part 3 of the "Mastering Drupal 8 Multilingual" blog series provides site building and front-end tips and techniques to improve the multilingual experience for both editors and end-users.

Previous posts in this series covered planning and budgeting for multilingual, as well as the process for installing the modules needed and the basics of content, configuration and interface translation. If you missed posts one or two, you may want to read those posts before proceeding.

Aug 12 2019
Aug 12
Image of the Rossetta Stone

In Mastering Drupal 8 Multilingual: Part 1 of 3, we focused on planning for Drupal 8 multilingual and its impact on a project's timeline and budget.

In Part 2 (below), we cover everything you need to know to have a functioning multilingual site with no custom code. Part 3 of the series covers more advanced techniques for site builders and front-end developers.

Aug 08 2019
Aug 08
Text on the Rosetta Stone

The web is constantly growing, evolving and—thankfully—growing more accessible and inclusive.

It is becoming expected that a user can interact with a website solely via keyboard or have the option to browse in their native language. There are many ways to serve the needs of non-native-language users, but one of the more robust is Drupal Multilingual.

Unlike 3rd party translation plugins like Google Translate or browser translation tools, Drupal's suite of core Multilingual tools allows you to write accurate and accessible translated content in the same manner as you write in your default language content. With no limit on the number languages, settings for right-to-left content, and the ability to translate any and all of your content, Drupal 8 can create a true multi-language experience like never before.

There is, however, a bit of planning and work involved.

Hopefully, this blog series will help smooth the path to truly inclusive content by highlighting some project management, design, site building, and development gotchas, as well as providing some tips and tricks to make the multilingual experience better for everyone. Part one will help you decide if you need multilingual as well as provide some tips on how to plan and budget for it.

Jan 10 2018
Jan 10
Blue path through a white maze

Setting up a robust Drupal internal site search that searches all of the content that you add to a complex site can be a bit like finding your way through a maze. 

Drupal 8 core Search has been revamped and is much more powerful and accurate than in D7, but it still concentrates on text in nodes and not other entities those nodes might contain—like Paragraphs, Views, or custom blocks. Core Search also does not allow you to choose which fields you want to index, how important those fields are, or use any preprocessors to tailor your search. Search API gives you all this and more.

Search API is a Drupal contributed module that allows you create searches on any entity known to Drupal. You can use Views to create a custom search results page with specific filters. You can create different indexes tied to specific sections or content on your site. You can do just about anything to architect your search experience other than use the core Search block—which is really the only thing that makes core Search worth using. This post however, will show you how to take advantage of the power of Search API, and keep your site search box.

Dec 14 2017
Dec 14
Green twig closeup

In the recent post Twig for Drupal 8 Development: Twig Templating Part 1, we covered some Drupal Twig templating basics like debugging, custom templates, inheritance, variables, filters, attributes, and macros. This post will cover more advanced topics. You will learn about preprocessing variables, expanding the available templates with theme suggestion, Drupal 8 Views and Twig, and the Twig Tweak module.

Dec 13 2017
Dec 13
Branch in dark forest

Twig is a PHP templating engine and the default templating engine for Drupal 8. Part of the Symfony Framework, Twig syntax compiles templates down to plain PHP when rendered in the browser.

Twig offers advanced features like template inheritance, automatic escaping, variable filters and macros to improve development workflow. Drupal 8's Twig templates are "html.twig" templates, which means that you can mix Twig into HTML easier than you could mix PHP and HTML in Drupal 7’s PHP templates.

Syntax in Twig is somewhat different than PHP, with three main kinds of delimiters:

  • {{ }} prints the content of variables or expressions. This is the equivalent of PHP’s print or echo.
  • {% %} executes "if" statements, variable definitions or for loops.
  • {# #} adds template comments that are not rendered in the page.

A very basic Twig structure to print a message using a variable might look like:
{%  set message = ‘Welcome to  my great website‘ %}
{{ message }}

Dec 13 2017
Dec 13

After setting up aD8 site and going into the theme folders for Bartik and Classy you'll notice that there are lot of templates in D8. This is because Drupal 8 really takes advantage of Twig’s template inheritance capabilities. Twig allows templates to be extended, included and embedded into other templates which allows for a very atomic approach to site building. Extends, Include, and Embed are quite similar, but there are some key points to be aware of.

Use Extends to inherit a parent twig template

Extends brings in the parent template (the one being extended) into the child template. No content outside of blocks defined in the parent template will be allowed in the child template. In a parent paragraphs template (paragraph.html.twig) there are some default classes and html structure you'll want to set that will be used in every paragraph bundle you create:

In a child text paragraph bundle (paragraph--text.html.twig) you would extend the parent template (paragraph.html.twig) and switch out the block content so the child gets the classes you want from the parent but uses its own content.

Since the parent template is being inherited with extends, all content in the child template must be inside a block defined in the parent. Content outside of parent blocks (as shown below) will not be allowed and will throw a Twig error on your site.

Use include to insert one template into another

Include also inherits content of a file, but also allows variables from the current template to replace those from the parent template. Include also differs from extends in that template you are including is included directly where the call is placed in the child. Think of it this way—extends is like bringing a parent template into a child template and changing some of the content of the parent in the child. Include brings a child template into a parent by inserting the entire child template into the parent a specific point. You could also insert an entire parent into a child and replace variables but not content.

The biggest advantage of this in my opinion is including templates from outside a Drupal site into a Drupal site or from one entity type to another. We use Pattern Lab as part of our approach to theming but while our Pattern Lab instance lives inside our Drupal theme it is technically outside of the Drupal site structure so it cannot use variables like {{ content.field_long_text }}. It even has a different suffix for files: paragraph.twig instead of paragraph.html.twig.

To get around that we use include instead of extends and use the ‘with’ function to replace variables from Pattern Lab in Drupal. The parent template paragraph--text.twig in Pattern Lab extends the Pattern Lab paragraphs.twig template to get the html structure then adds example {{ text }} variable content defined in a yml file. To get the final Pattern Lab example output.

Then in Drupal, the paragraph--text.html.twig file uses include to bring in the entire content of the Pattern Lab paragraph-text.twig file and replaces the {{ text }} variable with the Drupal output of the long text field in my text paragraph bundle {{ content.field_long_text }}.

The Drupal template uses the Component Libraries module to find the Pattern Lab Twig template and includes all the Pattern Lab structure but uses the Drupal text field for content.

Embed a twig template to replace variables and override parent blocks

Embed combines include and extends. You can embed a template in another template and replace the variables using 'with' and switch out block content from the child template you are embedding into the parent (or vice versa).

An example of this would be creating paragraphs demo content in Pattern Lab and bringing it into Drupal. Since Pattern lLb doesn’t have modules, we have to hand build the paragraph's HTML structure then exclude it in Drupal (since we don’t want the hand-built paragraphs html structure and Drupal’s).

In Pattern Lab the text.twig template gives basically the same HTML structure that the final Drupal paragraph bundle does but uses some dummy text from a yml file.

The Drupal template paragraph--text.html.twig both extends and embeds templates. It extends the Drupal paragraph.html.twig to add bring global classes and html structure into the text bundle template and it embeds the Pattern Lab text.twig template in place of the parent paragraph.html.twig content block while replacing the {{ text }} variable with the Drupal {{ content.field_long_text }} variable. Adding comments to the plwidgetopen and plwidgetclose blocks prevents them from printing the paragraph structure created in Pattern Lab.

With the setup above, you can theme the Drupal text bundle directly in Pattern Lab and have whatever structure is built around the text variable be reflected both there and around the Drupal long text field as well.

Pro Tips:

  1. It is often common to get ‘template not defined’ errors when using include, extends, or embed. You need to make sure that either the template you are inheriting is defined in the theme registry through a theme suggestion hook or that you define the correct path in your inheritance delimiter so drupal knows where to look {% include directory ~ '/templates/widgets/text/text.twig' %}.

  2. Blocks are your friend. Block structure can be switched out or added to at will with any of the inheritance methods and placeholder blocks can be used in parent templates to allow for later customization. You can use placeholder header and footer blocks in page.html.twig file to allow for custom scripts, libraries and other code to be added to different content types as needed.

Oct 18 2017
Oct 18

We’ve covered writing fun and fancy CSS through a preprocessor, using a framework or library to take the pain out of JavaScript, and putting a task runner to work bring it all together. Lastly, we need a proof reader. Some way to know that what we built is working or tell us what’s wrong.

Think back over all the time you’ve spent trying to find a missing semicolon or unclosed bracket that brought a project to its knees, while you manually scanned 1000s of lines of code to figure out what you did wrong. Wish you had that month or so of your life back? Tools like Stylelint, ESLint, and your browser’s built in development tools will not get that time back for you, but they will help prevent that pain from happening again.

Stylelint and ESLint are command line lint programs that comb your code and compare it against a set of specified rules. You can write your own rules, use an existing library, or a combination of both. Your linting can be targeted to follow a set of best practices, just the rules you most care about, or help you overcome bad coding habits.

For instance, you can lint your Sass with Stylelint to show an error when you use spaces instead of tabs, leave too many blank lines after a block, or miss a semi-colon. ESLint can lint your javascript to detect if you are missing a bracket somewhere or have a comparison in which both sides are the same. For more in-depth information on Sass linting with Stylelint read my recent blog post Sass Lint: or How I Learned to Love the Lint.


Another critical front-end tool is web browser developer tools. Firebug was an early version of these tools, available in Firefox, but now all browsers come with a set of developer tools. These developer tools allow you to inspect your CSS and HTML, test and debug style rules directly in the browser, and look for errors in the JavaScript console. A browser like Chrome even allows you to slow and stop animations, set the color scheme of the inspector, view print styles, and expand minified CSS and JS source files.

Oct 18 2017
Oct 18
Toolbox top shelf filled with used tools.

Front-end development in 2017 is a complicated and constantly shifting landscape of frameworks, trends, libraries and strategies. It seems like there is a new ‘must use’ tool every few months. It can feel as though you’re drowning in quicksand trying to keep your head above the latest trends. 

When you look at your front-end tool box, do you feel more like Bob Vila or Bob Saget? 

Bob Vila in front of drywall with arms crossed Bob Saget with arms crossed


May 11 2017
May 11

Step 8: Set up a Custom Button in the WSIWYG Editor

In order to embed media, there needs to be a new CKEditor embed button to reference it (/admin/config/content/embed). Let's do this choosing "add embed button."

Once the button's embed type is changed to 'entity', more options become available–you can select "media" as the entity type, choose the types of media to display, and select the allowed display plugins. Display plugins are the display modes you enabled on the media bundle earlier. 

I recommend leaving all the media types blank so all types are allowed, but limiting the allowed display plugins to help keep the look of embedded media consistent. Notice that "default" is not a display option—that's why you need a "Full" display mode if you're planning on displaying images at their original size.

After creating the embed button, it can be added to the CKEditor formats. The new media embed button will be in the row of available buttons and can be dragged anywhere you prefer within the toolbar. I recommend removing the default CKEditor media button once your custom entity button is in place to prevent confusion.

Make sure to check display embedded entities, align images and track images for enabled filters and uncheck caption images if using a custom caption field. The filter processing order should have the three image filters at the top in the same order as their checkboxes appear.


If you are limiting allowed html, you will need to add the following tags into the allowed html tags field in order to allow media:

<figcaption> <picture srcset media type> <iframe src class title frameborder aria-describedby tabindex allowtransparency style> <drupal-entity data-entity-type data-entity-uuid data-view-mode data-entity-embed-display data-entity-embed-display-settings data-align data-caption data-embed-button>

May 11 2017
May 11
Bookshelf with vintage books, speakers and tvs

It seems like every Tom, Dick and Harry content management system gives editors a way to easily manage their media. So why should media be a struggle in a platform as powerful as Drupal?

At its core, Drupal 8 offers just a lonely image or file field that forces an editor to upload new media from their desktop. Thankfully, the built-in WYSIWYG editor (CKEditor) now adds the ability to caption images and there are rumblings of a core media library solution in future Drupal versions. But for now, straight out of the box Drupal 8 media implementation still seems limited and dated.

Yet all is not lost

With the right configuration and no custom code, you create a media solution with that is:

  • responsive
  • field-able
  • embeddable
  • caption-able

This is the first post explaining how we manage Media and Drupal 8 at Electric Citizen.

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web