Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Nov 23 2021
Nov 23

At Redfin Solutions, we strive to offer our clients holistic guidance to help them achieve strategic goals and create a long-term vision for their web presence. We also know that sometimes priorities change quickly. A website’s flexibility is as important as scalability, and the stability of centralized web operations shouldn’t come at the expense of limiting stakeholder decisions.

With these ideals in mind, we developed our Delta Site System (DSS) to help clients who have a need to quickly launch and maintain new Drupal websites. DSS gives Redfin’s clients the ability to define a “template” website from which others can quickly be deployed. These new sites can use the same themes (look and feel), modules (enhanced functionality), and configuration (content types and taxonomies), while also allowing for customization at the individual website level.

For large organizations with decentralized governance or a large volume of websites to manage, our Delta Site System is a gamechanger. Let’s take a closer look at how it works and the value it provides.

How the Delta Site System works

To build Delta Sites, we leverage Pantheon’s Custom Upstream technology. In the Pantheon website management platform, an Upstream is a repository that acts as a parent for another repository. When changes are made to code or configuration, updates are pushed downstream, meaning from parent to child. A Custom Upstream is the parent repository for an organization or set of sites. For Redfin’s Delta Sites, it holds an all-inclusive Drupal package custom-built to the needs of each client from which additional websites can be created.

Since each individual website still has its own independent “container” with a development, test, and production environment of its own, additional customizations can be made on the site level without affecting other sites. However, when important updates need to be made across the board, changes can be pushed to all sites without causing conflicts.

The diagram below helps explain the workflow.

Redfin Solutions Delta Site System custom toolkit: Drupal Core CMS, content management paradigm, common components and content types, and styles and brand identyRedfin Solutions Delta Site System custom toolkit: Drupal Core CMS, content management paradigm, common components and content types, and styles and brand identy

Reaping the benefits of the Delta Site System

So, how is this a game changer? Redfin’s Delta Site System fills the gap between flexibility and scalability that’s been historically hard to bridge by embracing the push and pull of cohesion and agility. 

Every Delta Site System we build for a client is customized for their specific needs and defined in Redfin’s discovery process with the client—so there’s no cookie cutter site cloning. However, our DSS clients will reap some of the benefits across the board.

Maintain standards across multiple websites

With a Delta Site System in place, it’s easy for a client to determine which standards need to be maintained between their multiple sites and to ensure these standards are adhered to. For instance, it might be important that certain taxonomies are consistent from site to site so that content is organized in a similar fashion. Or maybe the standards are more stylistic, with items like menus, color palettes, and visual components remaining consistent across each site. Of course, security and technical standards are always maintained across every web property.

Provide flexibility to individual website stakeholders

At the same time, a custom-built Delta Site System allows for greater flexibility on individual websites because new functionality and features can be added without impacting other sites in the system. For instance, Redfin built a front-end paradigm using Bootstrap Paragraphs for a client with in-house knowledge of CSS, giving them near-infinite flexible layouts to use on dozens of distinct websites in their purview. For other clients using DSS, the flexibility to use custom features on certain websites helps prevent content editors on other sites from getting bogged down in irrelevant options, leading to streamlined publishing.

Reduce time spent managing web properties

Some of our clients have the bandwidth and desire to build new sites entirely on their own. Others rely on Redfin to help implement each Delta site. Either way, the Delta Site System reduces time and resources spent on managing feature and security updates on disconnected web properties and frees up developer time for building new features and components.

Re-use favorite components and features

Speaking of time savers, once an element is added to a website in a Delta Site System, Redfin can add it to a client’s custom upstream to apply it to any and all sites in the system. That means there’s no need to reinvent the wheel for every custom site request. For example, one of our clients has a Delta site with a content carousel feature enabled. If the feature becomes relevant for another one of their sites later on, DSS allows them to easily add it in, without spending extra money to develop the feature.

Content carousel exampleContent carousel exampleThis content carousel is an example of a custom-built element for one of our clients. It is one of a large collection of elements they can use to build layouts.

Make website management more accessible

Because launching a Delta Site doesn’t require advanced technical knowledge and making a mistake on one website doesn’t affect another, the Delta Site System expands the scope of who can administer websites. Rather than relying on one person or department for all website changes, more team members can be involved in the process, which can simplify workflows, give more folks access to web publishing, and reduce red tape for large organizations.

Use case: Dartmouth College

When Redfin began working with Dartmouth College’s Advancement Division in 2019, the Dartmouth team was facing a challenge. In addition to their main web property the Alumni Relations website, they’d collected several other websites over the years, and each one was built using an entirely different paradigm. Moreover, the need for new websites—for campaigns, conferences, and events—was now increasing.

Redfin created a custom Delta Site System for Dartmouth that hosts their current websites and allows for the easy creation of new ones. Redfin built a custom collection of Paragraphs (or components) with elements such as accordions, carousels, and hero images. Then, using Bootstrap Paragraphs, Dartmouth site editors can apply Bootstrap classes to their Paragraphs to further customize the layout of a page.

Four similar, but separate examples of Dartmouth College Delta SitesFour similar, but separate examples of Dartmouth College Delta SitesWith the Delta Site System, Dartmouth is quickly able to spin up sites for events, conferences, and new initiatives.

Redfin’s Delta Site System has helped Dartmouth cut down on the time spent managing and standardizing ad-hoc websites while simultaneously giving more freedom to site administrators and editors.

Get started with the Delta Site System

The first step to getting started with the Delta Site System—or to see if it’s the right fit for your organization—is a consultation with a member of our team. Reach out today to speak with Redfin Solutions about how we can help you define your web goals and make them a reality.

Nov 03 2021
Nov 03

The state of website accessibility

Research conducted by WebAIM, a leading nonprofit organization based at the Institute for Disability Research, Policy, and Practice at Utah State University, found that 97.4% of home pages evaluated contained accessibility errors in 2021. You may be wondering how many users are affected by these errors. Put simply, the answer is a lot.

More than 14 percent of adults in the U.S. experience difficulty hearing and more than 16 percent have vision impairments, according to the CDC. Even before accounting for disabilities related to motor skills or cognition, this means tens of millions of people in the United States alone may be blocked from engaging with your content or finding the information they need on the internet. 

Additionally, people may experience a “temporary disability” due to environmental conditions (e.g. poor lighting). It is likely that as we age, all of us will experience some form of disability. Moreover, different devices and internet connection speeds can affect one’s ability to access content. Accessible website design truly benefits all of us and helps create a more equitable society.

WCAG compliance and the ADA

WCAG is developed by the World Wide Web consortium (W3C) in coordination with organizations all over the world. The goal of the guidelines, as stated by W3C, is to provide “a single shared standard for web content accessibility that meets the needs of individuals, organizations, and governments internationally.” 

WCAG documents provide a number of success criterions that a webpage must “pass” to be considered accessible. These criteria are broken down into four categories: perceivable, operable, understandable, and robust. There are currently two versions of WCAG (2.0 and 2.1) and three levels: A, AA, AAA. WCAG 2.2 is expected to be published before 2022 and will include all the elements of the previous versions, with new proposed success criteria added.

In the United States, digital accessibility is protected by the American Accessibilities Act, or ADA.  While there is not yet a federal law dictating a specific WCAG mandate for website ADA compliance, many lawsuits have been successfully fought against owners of web properties for failing to meet the needs of people with disabilities. For instance, lawsuits brought by the National Association of the Deaf against MIT and Harvard culminated in 2020 with both universities legally consenting to provide high-quality captions for all online video content. After the Covid-19 pandemic hit, lawsuits against educational institutions skyrocketed as it became clear that people with disabilities could not adequately access educational content online and that the issue was urgent.

What makes websites accessible

Website accessibility revolves around four user-centered principles: they must be perceivable, operable, understandable and robust. These principles are sometimes referred to using the acronym POUR. Each principle is explained below, along with examples of how the principle applies to website design and development.


The “perceivable” principle states that information and user interface components should be presented to users in ways that they can perceive. For instance, the criterion that text alternatives must be provided for any non-text content falls under this rule. You may already be aware that most images need to be accompanied by alternative text content that accurately describes the content to users who cannot see the screen. Similarly, input fields must be labeled or named programmatically so that the field can be identified by a screen reader or other assistive technology.

The perceivable rule also dictates that color plays an important role in accessible website design. While color cannot be the only means of conveying information or indicating an action, minimum color contrast plays an important role in the visual presentation of text. Many websites use color schemes that aren’t perceivable by people with impaired vision, including many types of colorblindness. In order for most text to be considered compliant, it must have a contrast ratio of 4.5:1. Luckily, website designers can use a number of tools to determine exact color contrasts and develop effective, accessible color palettes.


In order for a website to be “operable,” its user interface and navigation components must be functional for all users. A large component of operability is keyboard accessibility. Content that is operable only through mouse clicks will not be usable for folks who cannot use a mouse. And while some folks may not be able to use a standard keyboard, most adaptive technologies emulate the keyboard. This makes keyboard accessibility important to provide access to people with motor disabilities, people who are blind, and people with conditions such as tremors.

The operability principle also applies to the ways that users find and navigate content on your website. Many people don’t realize the importance (or existence!) of semantic structure in websites. Semantic structure—implemented through HTML elements such as regions, headings, lists, and ARIA specifications—is essential to helping users with and without disabilities get the information they need from your website. It is particularly important to folks using assistive technologies, such as screen readers, so that they don’t have to comb through every word on the site to find the content they need.


The “understandable” principle speaks to a user’s ability to understand the user interface and the information it contains. This principle includes elements of design, development, and the content itself. For instance, one component of understandability is readability. This includes publishing content at the lower secondary education level and providing mechanisms for identifying jargon words (or avoiding them altogether!) and abbreviations.

In addition to the readability of text, an interface must be predictable and offer input assistance to help users avoid and correct mistakes. This includes making sure elements that perform the same function are labeled consistently and appear in the same order, where relevant. For instance, a button labeled “Previous page” should not be labeled “Go back” in another location. These types of labels are most often implemented programmatically by developers as they create your website. Similarly, error prevention, such as letting a user know when a form input isn’t valid or a field, is required as part of what makes a website understandable.


To be considered technologically “robust,” an interface must be able to be interpreted reliably by a wide variety of “user agents” — mainly browsers and assistive technologies. One of the main elements of robustness is called parsing, which means that mark-up languages such as HTML must be formatted and nested according to proper specifications so that they can be properly analyzed and interpreted by these user agents. A simple extra quotation mark or forgotten angle bracket could make a web page programmatically unreadable.

Another important consideration for robustness is the implementation of status messages. This criterion states that status messages should alert users without interrupting the workflow of a user of assistive technology. For instance, if a user is scrolling through a social media feed when an alert message pops up, the user should be made aware of the alert without the focus (the input area of the screen that receives keyboard input) shifting.

Focus on accessibility, every step of the way

To ensure that websites meet the needs of all users and are WCAG compliant, it’s important to prioritize accessible website design every step of the way—from user experience research to content entry.  Here’s an overview of the type of accessibility work that happens throughout the web design and development process.

User experience research

User experience (UX) research is the study of end users and their requirements and wishes. While much user experience research is conducted before a project even begins, the UX project should be iterative — with a testing and feedback cycle that continues even after a website is launched. Accessibility should be taken into account from this early stage in identifying the needs of the users. This can be done by incorporating users with disabilities in the research, building accessibility considerations into personas and user stories, and testing prototypes at various stages using assistive technologies.

User experience design

The UX design process—to include information architecture (organization) and interaction design—can help head off accessibility concerns down the road by ensuring that simplicity, consistency, and user needs are the backbone of a website. At this stage, accessibility can be built in by establishing consistent navigation, metadata, and taxonomies, planning for consistent UI components to be used across a website, and determining the hierarchical and semantic structure of web page templates.

At this stage, designers also consider how to convey information and offer user input across different devices, develop alternatives to motion for alerts and emphasis (which can cause harm to people with certain conditions), and ensure that a meaningful linking strategy is employed to avoid the use of inaccessible “click here” links throughout a website.

Visual design

In the visual design stage, the perceivable principle takes center stage. Visual designers develop accessible color pallets, decide on typefaces and font sizes for various user interface elements, and ensure element selection and alerts are conveyed without color alone. 

Visual designers also play a role in consistency (an important feature of the understandable principle) by ensuring the consistent patterns built into the information architecture are conveyed graphically.


The development stage is where the bulk of accessibility implementation happens. It’s at this stage that mark-up elements are created and formatted according to specifications with proper names and labels. CSS is used to implement accessible styles, responsive designs, and media queries, and create interactivity with scripting languages. Developers build in keyboard accessibility so that any interactivity, any action a user can take using a mouse, can also be performed with a keyboard or device that uses keyboard inputs.

Developers can also implement Web Accessibility Initiative – Accessible Rich Internet Applications, better known as WAI-ARIA or simply ARIA. This framework helps assistive technologies properly interpret interactive website components (e.g. sliders or accordions) by providing additional attributes.

Content entry

Entering accessible content into a content management system, such as Drupal,  is the final step. This includes ensuring images and non-text images have helpful alternative text, using headings in the proper order, and providing high-quality captions and/or transcripts for audio/video content. Learn more about writing accessible web content on our blog from one of our designers.

Feeling overwhelmed? Get in touch!

If you’re new to accessible website design or WCAG compliance, this might seem like a lot to keep in mind! At Redfin Solutions, we pride ourselves in meeting our clients where they are, and we’re here to help with important web considerations like accessibility. 

If you’d like an accessibility audit on an existing web property or are interested in starting an new accessible project, get in touch!

Sep 22 2021
Sep 22

Why upgrade Drupal 7 to Drupal 9

First things first: why is a Drupal 7 to 9 upgrade even necessary? In short, Drupal 7 will soon cease to be supported and upgrading to Drupal 9 will ensure your website uses the most secure Drupal code. It will also give you access to exciting new features such as the Layout Builder module for easily creating visual layouts with a drag-and-drop interface, out-of-the-box multilingual capabilities, and the ability to quickly make small content changes without navigating to the edit page.

Drupal 7 will reach its end-of-life in November 2022. Drupal 8 introduced a paradigm shift in configuration management, coding methodology, and theming (the way a website is styled).  However, the differences between Drupal 8 and Drupal 9 are minimal. For this reason, the Drupal community originally recommended migrating incrementally from 7 to 8 and then 8 to 9. However, an extension of Drupal 7 support due to the Covid-19 pandemic shifted timelines around. Now, Drupal 8 is actually reaching its end-of-life before Drupal 7, on November 2nd, 2021. With this in mind, it makes sense for many Drupal 7 websites to upgrade directly to Drupal 9.

What is unique about this upgrade

Unlike past Drupal upgrades, a lot is changing when you go from 7 to 9. While these changes are widely seen as improvements for developers, content creators and end users alike, it means an upgrade from Drupal 7 to Drupal 9 could require more time and resources than other upgrades. To upgrade from Drupal 7 to any newer version of Drupal, a website needs to be almost entirely rebuilt — there is no upgrade “button,” unfortunately. Rather than porting over themes and custom modules, developers may have to write a lot of new code to get a site up and running on Drupal 9. But don’t worry—this doesn’t mean you’ll have to rewrite every blog post and staff bio! Most content can be migrated relatively seamlessly by an experienced Drupal developer.

Drupal upgrade considerations

To determine how large of a project your Drupal 7 to 9 upgrade will be, take some time to think about the following factors that are likely to affect project scope.

The size and complexity of your website

This one might seem like common sense: The larger and more complex your website is, the more resources will be needed to recreate it on Drupal 9. Determining the size of your website should be relatively simple. You can get a count of the number of nodes or pages your site contains by exporting pages from Drupal, consulting your XML sitemap, or using Google Search Console to see the number of pages crawled for tracking by Google. If you’re unfamiliar with administering your site, a developer can help you determine this by running reports that group the amount of content per type.

Determining the complexity of your site can be a bit more challenging, but it’s also likely to carry more weight in determining the scope of your upgrade. Generally speaking, the number of content types, taxonomies, views, modules, and custom fields your site uses will greatly affect the developer time needed for the upgrade. For instance, if your website has 15 content types, each with their own unique data fields and designs, a developer will need to recreate and then restyle each of those page templates. Some other complexities may include faceted search indices that allow users to apply filters to specific types of content, multilingual features, and custom modules or other custom code.

The Drupal modules you currently use

As mentioned in the last section, custom modules will require significantly more resources to upgrade than contributed or core Drupal modules. This is worth repeating because custom modules will need to be entirely rebuilt in the new Symfony framework (the back-end PHP framework that’s used in Drupal 8 and beyond) and because migrating the content in custom modules is itself a time consuming task that’s necessary to ensure no content is lost.

However, even “standard” Drupal 7 modules may not migrate seamlessly to Drupal 9. Modules that you currently use may not yet be supported on Drupal 9, or they may have been discontinued altogether in favor of newer modules that better conform to today’s best practices. If this is the case, time will be spent to determine what Drupal 9 modules can take their place.

Your required website integrations

Does your website have a reservation system that is connected to third party software? Perhaps you use a calendar integration or have data that maps directly to a CRM like Salesforce? Knowing what integrations your site needs to support, how flexible you’re willing to be with third-party software, and how customized your integrations are (i.e. is there an API module used “out of the box” or was custom code written to sync data from one platform to another?) will help you determine whether integrations will significantly affect the scope of your upgrade.

Your ideas for a refresh or redesign

With an upgrade from Drupal 7 to 9, a website rebuild is guaranteed. However, how many changes you make to your website at the time of the upgrade is up to you. Consider whether a website redesign or a refresh is appropriate for your brand and your budget.

Many companies and organizations use the upgrade as an opportunity to audit, refresh, or even entirely redesign their website. While incorporating a redesign likely means allocating more resources, it also means getting the most value for your time and money while you’re already “under the hood,” so to speak. Even if you don’t opt for a full redesign at the time of your upgrade, it’s a good idea to audit your site and determine if there are any outdated features, functionalities, or content that simply don’t need to be migrated or could be implemented more efficiently.

How to get started with your upgrade

The first step in any upgrade is to take stock of your current website. This should involve an audit of your modules, content, and important features. Next, you’ll want to start thinking about your roadmap for the future. For instance, is now the right time to consider a redesign? What organizational goals or plans may affect your upgrade timeline?

If you need help getting started with an audit or strategizing for the future of your site, get in touch with the Redfin Solutions team today to start planning your Drupal upgrade!

Aug 27 2021
Aug 27

Whether you’re launching a completely new Drupal website or it’s time to consider redesigning an outdated website, the prospect of finding the right web design agency can feel like a daunting process. However, to meet your business goals and users’ needs, choosing the right firm is an important step.

Drupal excels at providing an easy content authoring experience for complex websites. You’ll want to make the most of its scalability and flexibility by working with web designers and developers that understand Drupal design. Here are some key aspects to keep in mind when thinking about your Drupal design process, looking for a Drupal web design agency, and making sure you can recognize red flags.

What to know about Drupal design

It's not (quite) a blank slate for designers

It’s true that Drupal is highly flexible. You can customize almost everything on your Drupal website, from layouts and colors to content organization and integrations. However, it’s important to keep in mind that as a content management system (CMS), Drupal relies on some standard “building blocks” to allow for quick and consistent content authoring. Every Drupal website has a Theme, or a collection of files that define the presentation of your website. In addition to standard assets like CSS and Javascript files, some of these are Drupal-specific files. For instance, Drupal regions must be added to a theme to control where the content is displayed and how the page is marked up in HTML. It’s necessary for Drupal web designers to understand the basic mechanics of a Drupal website and understand how design concepts will translate into Drupal development.

Design is component based

If you’re following recognized best practices for scalable web design and development, you’ll want to think about your Drupal design in terms of components rather than just pages. In practice, component-based design (also called Atomic Design) means that designs are broken down into smaller component parts that can be combined and rearranged in a number of ways to create different page templates. For example, your smallest components may include buttons, labels, and input boxes. These components always look the same, but they can be re-used and rearranged to create search bars, sign-up forms, or calls to action. These elements can then be combined with others to create larger elements such as headers or modals. 

While component-based design is popular across the web, it’s especially important for Drupal websites in order to take advantage of the flexibility and scalability Drupal offers while maintaining consistency and easy content authoring across a complex website. Drupal 8 has modules such as Layout Builder (included with the Drupal Core distribution) and Paragraphs that make implementing component-based design much easier than it’s been before.

A button component placed in an example designA button component placed in an example designIn component-based design, smaller component parts are combined and rearranged to create larger elements and templates that can be reused in a number of ways across a website.

Your information architecture matters

When you think of a website design, visual elements like colors, images, and typography probably come to mind. These visual components are undoubtedly important, but it’s likely that the information architecture underlying the visual design is just as important—if not more important—to helping users find content and maintaining an attractive, consistent, and user-friendly website. Some ways that information architecture is manifested include site maps, hierarchies and categorizations (i.e. taxonomies), navigation, and metadata.

Choosing the right Drupal web design agency

Now that you know the basics of what designing a Drupal website entails, how do you find the right agency for the job?

Look for Drupal design examples

Often, the most sure-fire way to see whether an agency has the Drupal design experience you’re looking for is to check out the other work they’ve done. Think about the different features of your web design project that are the highest priority or may be unique to your website and make sure the agency you hire has a track record of success on similar projects. For instance, if you’re redesigning a website for a university office, you may look for companies that have previously designed higher education websites. Or if your website needs a reservation system, check if the agency you choose has experience integrating websites with reservation software and constituent relationship manager (CRM)s. Of course, you’ll want to ensure the examples you see are from Drupal websites!

Blue design elements used throughout the University of New England's websiteBlue design elements used throughout the University of New England's websiteDrupal is a common platform for university websites. Redfin has designed and maintained a number of higher education sites, including the University of New England.

Ask about the design process

If you’re unsure about an agency’s design process or it’s not clear in their proposal, it’s more than okay to ask! The agency you choose should have an established “Discovery” phase devoted to understanding your business goals and your users. This might involve creating user personas or defining the key tasks you expect users to be able to accomplish on your website. You may also want to gain clarity about what design deliverables they’ll provide. Depending on the size and scope of your project, this might involve sitemaps, user journeys, wireframes, or design mocks, for instance. Most importantly, ensure that the design process is user-centered.
These days, it’s a good sign if an agency follows an agile approach to design—meaning work is conducted iteratively in two week increments called sprints. The Agile methodology allows stakeholders to provide more feedback and re-examine goals as the project moves along. You can also ask about how designers and developers at the agency work together. A good rapport and established workflow between designers and developers goes a long way toward ensuring your final product looks like the mocks a designer shows you.

Check out their involvement in the Drupal community

The best way to tell whether an agency has real Drupal credentials is to take a look at their involvement in the Drupal community. If they’ve contributed code to Drupal modules or have played a part in organizing Drupal events, it’s likely they’ve committed to keeping up with best practices for designing Drupal websites. At Redfin Solutions, for instance, we regularly sponsor Design 4 Drupal, Boston, an annual conference devoted to design, UX, and front-end development for Drupal websites.

Design 4 Drupal, Boston 2019 attendees in a lecture hallDesign 4 Drupal, Boston 2019 attendees in a lecture hallThe Redfin team (bottom right) at the Design 4 Drupal conference in 2019. Redfin sponsors the conference annually.

Assess their communication style

Remember, you’re going to be working closely with the web design agency you choose. Beyond technical skills, it’s important that a web design agency prioritizes communication skills and customer service. Even the most genius tech wizards are only as good as their ability to communicate with you and listen. After all, it is your website.

Red flags: what to look out for

Don’t get caught off guard when it’s time to launch your website. Keep these red flags in mind when you’re choosing an agency to ensure a successful project.

Avoid designers who don't know Drupal

There are many great web designers out there that aren’t familiar with Drupal. You should avoid them if you’re building a Drupal website. This isn’t because their designs won’t look great on Drupal—it’s because there’s a good chance they won’t know how to implement them in a Drupal environment. This applies to any software or content management system. Choosing a web design agency that specializes in the platforms that your website uses will ensure you get the most out of the technology you’ve got.

Beware an inadequate discovery phase

In an attempt to provide you with the lowest quote possible, a design agency might nix or skimp on the discovery phase. But without this essential first step in the process, an agency can’t possibly build a user experience that delights your users and helps you achieve your business’s specific goals. When it comes to Drupal design, context is everything. Make sure the agency you choose for your project takes the time to understand the environment in which you operate rather than just churning out websites factory style.

Steer clear of agencies that don't mention accessibility

If a proposal from a web design agency doesn’t mention how they’re addressing web accessibility or usability, you should consider this a red flag. Following accessibility standards in design and development allows users with disabilities, such as visual impairment or limited mobility, to access your content—and helps everyone find the information they’re looking for. Depending on your website’s domain, it may even be legally required that your website meet WCAG criteria. When it comes to accessibility, there are no shortcuts.


Keep these tips in mind when you’re ready to find the right Drupal agency for you and your website. To learn more about user-centered web design for Drupal websites, visit our blog or contact us to see how Redfin can help!

Jul 20 2021
Jul 20

When you start with the wysiwyg-container div, you will see four direct children with the top-level class. Starting with the first child, test for each special case. One of the advantages of using a DOMDocument is that you can use the getElementsByTagName function to ask any DOMNode if it has children tags like img, table, or iframe. On a match, turn all the content in the branch to a new paragraph. Otherwise, put each chunk of consecutive text into a new text paragraph. Here lies the first problem with Benji’s template: branches with mixed content.

Most of the time this isn’t an issue. If there’s a table inside a div, you probably want the entire div for your table paragraph. However, if there’s an image inside an anchor tag, your image paragraph will grab the image data but ignore the link, losing data along the way.

{# Top level tag #}

This may be an acceptable loss, or an issue that can be flagged for manual intervention. Otherwise, you’ll need a method that can recursively traverse an entire branch of the DOMDocument, cherry-pick the desired HTML element, and put the rest into the default bucket.

For instance:

/** * Recursively navigate DOM tree for a specific tag * * @param $post * The full page DOMDocument * @param $parent * The parent DOM Node * @param $tag * The tag name. * @param string $content * The content string to append to * * @return [] * Return array of DOM nodes of type $tag */ static protected function recursiveTagFinder($post, $parent, $tag, &$current) { $tagChildren = []; // Iterate through direct children. foreach ($parent->childNodes as $child) { // DOMText objects represent leaves on the DOM tree // that can't be processed any further. if (get_class($child) == "DOMText") { $current .= $post->saveHTML($child); continue; } // If the child has descendents of $tag, recursively find them. if (!is_null($child->childNodes) && $child->getElementsByTagName($tag)->length != 0) { $tagChildren += static::recursiveTagFinder($post, $child, $tag, $current); } // If the child is a desired tag, grab it. else if ($child->tagName == $tag) { $tagChildren[] = $child; } // Otherwise, convert the child to HTML and add it to the running text. else { $current .= $post->saveHTML($child); } } return $tagChildren; }

If a top level DOMNode indicates that it has an img tag, then this method will search all the DOMNode children to find the img tag and push everything else into the default text paragraph, the $current variable. There will likely be some disjointed effects when pulling an element out of a nested situation: a table may lose special formatting or an image may not be clickable as a link anymore. Some issues can be fixed in the plugin. In the migration, I checked if any img tags had an adjacent div with the caption class and stored that in the caption field on the paragraph. Again, others may need to be manually adjusted, like reordering paragraphs or adjusting a table. Remember that it’s much faster to tweak flagged migration content than to find and fix missing data manually.

On to the next issue, let’s dig into embedded media in Drupal 7. The tricky aspect here is that the media embed is not stored in the database as an image tag, but as a JSON object inside the HTML. This requires a whole new set of tests to parse it out. To start, check each DOMNode for the opening brackets of the object [[{ and the closing brackets }]]. If it only contains one or the other, then there isn’t enough information to do anything. If it contains both, then get the substring from open to close and run json_decode. This will either return an array of data from the JSON object or null if it’s not valid JSON. The data in this array should contain an fid key that corresponds to the file ID of the embedded image. That file ID can then be used to grab the image from the migration database’s file_managed table and create an image paragraph.

Those are the main gaps in Benji Fisher’s custom source plugin. Of course each implementation requires even more tweaks and data manipulations to get the exact migration to work correctly. Some content simply will not transfer cleanly, so remember to test thoroughly and stay in tight communication with your client in order to turn WYSIWYG chaos into neat paragraphs.

If you found this migration series useful, share it with your friends, and don’t forget to tag us @redfinsolutions on Facebook, LinkedIn, and Twitter.

Jun 16 2021
Jun 16

In November 2022, the Drupal community and the Drupal Security Team will end their support for Drupal 7. By that time, all Drupal websites will need to be on Drupal 8 to continue receiving updates and security fixes from the community. The jump from Drupal 7 to 8 is a tricky migration. It often requires complex transformations to move content stuck in old systems into Drupal’s new paradigm. If you are new to Drupal migrations, you can read the official Drupal Migrate API, follow Mauricio Dinarte’s 31 Days of Drupal Migrations starter series, or watch Redfin Solutions’ own Chris Wells give a crash course training session. This blog series covers more advanced topics such as niche migration tools, content restructuring, and various custom code solutions. To catch up, read the previous blog posts Custom Migration Cron Job, Migration Custom Source Plugin, and Connecting a Transact SQL Database to Drupal.

Migrating from Drupal 7 to Drupal 8 often requires restructuring your content, like transforming an unlimited text field into paragraphs or a list text field into a taxonomy reference. The tricky part is that the migration pipeline wants each source entity to go to one destination entity, but each paragraph or taxonomy term is a new entity and a single node can reference several of these.

So how do you break up data from one entity and migrate it into multiple entities?

Manual entry

If there’s a small set of old content or you’re already manually adding new content, then manual entry is a viable solution, but it shouldn’t be the default for large migrations. Going this route, you want to set up content editors for easy success. If possible, reduce the number of actions needed for a repeated task. With some clever string concatenation in your query results, you can create exact links to all the node edit pages that need updating. This is much easier than giving someone a node id or page title and asking them to fix that page. Just because it’s not an automatic migration, doesn’t mean we can’t automate aspects of it.

The CSV Importer module is useful for simple data that already exists in a CSV file or can be quickly exported as a CSV file. For example, a spreadsheet with hundreds of country names could easily be imported as taxonomy terms with this tool. Or a list of emails and names could be imported as Users. Once you’ve migrated your data, you can reference them in other migrations using the static_map plugin or a custom process plugin to lookup the correct entity reference. Be careful not to abuse the static_map plugin with hundreds of mappings. In the country example, if the source data contains the name of the country that you want to reference in the destination, you could write a process plugin that gets the taxonomy id from the name. Remember that once entities are migrated you can use the full power of Drupal to find their id’s in later migrations.

Generate entities during migration

Use the entity_generate plugin or a custom plugin to create the entities during the migration process. This gives more control over how the data is transformed, but there’s no way to rollback or update the generated entities through the migration API. This shouldn’t be the default, but can be necessary for more complicated matters such as breaking down a dense wysiwyg field into separate paragraphs (see Benji Fisher’s custom process plugin).

Migrate entities separately with a custom source plugin

See our earlier blog post for a step-by-step guide on this. Drupal core provides lots of useful source plugins, but sometimes you need a custom query to migrate specific source data into entities. This approach gives you that flexibility within Drupal’s migration workflow. Unlike the previous option, you can still rollback and update entities and leverage all the other migration tools.

How you perform a data transformation like this is largely contextual, but these are powerful tools that can be used in many cases. Contact us with any questions regarding complex Drupal migrations, or if you are looking for a Drupal agency to help with your next website project.

May 26 2021
May 26

This year at DrupalCon North America Redfin Solutions’ CTO Chris Wells had the honor to speak for the first time at a DrupalCon. His presentation Migrating into Layout Builder had the privilege of being one of the most well-attended sessions of the conference.

The Client

Redfin Solutions has a longstanding relationship with the University of New England (UNE)--Maine's largest private university--and they were at a turning point where their previously cutting-edge website felt dated, especially the content editor experience. With Drupal 7's end-of-life on the horizon, we worked with them to come up with an upgrade plan to Drupal 8, so that we would have better access to a modern interface.

Previously, their Drupal website had been implementing responsive component-based design principles using WYSIWYG Templates. With more modern tools like Gutenberg and Layout Builder in core, we knew we had great options and opportunities to provide a better content editor experience.

The Transformation

We knew that we would have to find a strategy for migrating the older paradigm to the new paradigm, and for this we chose layout builder. With its core support and logical application of blocks as components, it was a natural choice. But, how would we get larger blocks of HTML into a place where all new pages were using the new paradigm of pages where each page is a Layout Builder override?

Luckily, Drupal has just such a way to transform data on input, which is the Migrate API. The Migrate API follows a common pattern in Computer Science called Extract, Transform, Load. In the parlance of our times (that is, Drupal), we use the phrases "source" (extract), "process" (transform), and "destination" (load). Each of these phases are represented by Plugins to the Migrate API.

Our Situation

In the case of UNE, we were migrating from (source) Drupal 7 nodes (the page body field) into (destination) "basic text" blocks. For the source, we used the live Drupal 7 database on Pantheon. The "basic text" block is the one that comes out of the box in Drupal 8 as a custom block type, and has a title and a body.

We did NOT go down the rabbit hole of regex'ing out each of the components, but rather we migrated the old body into the new paradigm, so that every page uses the same paradigm from the start, and content editors can expand into using layout builder overrides over time. We simply migrated in some legacy styles, which eventually we will discard. We had the staff and resources to clean up any egregious inaccuracy in the translation as needed, so this ended up being the most time-and-cost-efficient solution.

However, the real magic of this migration is really the process part, where we change the data into the format it needed for layout builder.

Layout Builder Storage

So first, we need to understand how Layout Builder actually stores things behind the scenes. Much like an entity reference field, layout builder is really storing a list of sections. When you build a page with Layout Builder, you are adding sections to it (a one-col, followed by a two-col, followed by another one-col, for example). Much like with regular field tables, it stores the entity ID, revision ID, delta (so it knows the right order!), and then some data value. For taxonomy term references, for example, it would store the "tid" for the term being referenced.

With Layout Builder, there's additional complication. Since each section may contain multiple components, there's an extra layer where we need to then store the components for a section each in their proper order.

For this, Drupal's Layout Builder is not nesting another set of entity references. Instead, it's actually storing a serialized Section object. One of the main tenets of a Section object is an array of SectionComponent objects, which each store their own location and position within the section.

The actual table where this information is stored is the [entity]__layout_builder__layout table in the database. Depending on which entity you've enabled Layout Builder overrides for, this may be the node__layout_builder__layout table, or the user__layout_builder__layout table.

Most layout builder SectionComponents are just "blocks" in the traditional Drupal sense of that entity. With that said, there is one new concept that should be introduced, which is whether or not blocks are to be considered "re-usable." Re-usable blocks are the ones you normally create from Structure > Blocks > Custom Block Library, and you then place to be "re-used" across the website, for example on a sidebar on every page.

Non-re-usable blocks are those which are created when you insert block content into a Layout Builder layout. The difference between these two is really just a boolean (and hidden) field on the block, which helps filter blocks using the UI.

And, the very last piece of the storage puzzle to be aware of is the "inline_block_usage" table. This simply stores the block_content_id, the layout_entity_type (ex.g. "node"), and the layout_entity_id (ex.g. "node id"). It's a record of where the non-re-usable blocks are, in fact, used.

OK, so let's do this!

We need to transform Drupal 7 node bodies into blocks, and then migrate the pages into pages, where the "body" of the node is now the Layout Builder overrides.

To do this, we are going to:

  • migrate bodies into non-re-usable blocks

  • migrate the nodes into nodes

  • be sure and link up the previously migrated blocks as Layout Builder Sections/SectionComponents

To help demonstrate these concepts, I've created a fully-functional website repo on Drupal 9 using some CSVs as a source. I'm going to dissect some of the main parts of that for you.

Step 1: Import the Blocks

In many ways, this is a very standard block migration, but the special thing to call your attention to is the "reusable" field in the "process" section:

  # whether or not it's reusable   reusable:     plugin: default_value     default_value: 0

View code on GitHub

This specifies that the blocks coming in are inline blocks. You may or may not want to use this, but we certainly did, and this is how you set it.

Step 2: Import the Nodes

In many ways, you are just migrating node fields in the way you normally would, mapping fields like title, uid, etc.

Where this one gets special is that we migrate into a field called layout_builder__layout which is the field that stores the overrides. With that, fields expects a Section object (or an array of Sections).

  # This is the layout_builder__layout field, which stores everything!   layout_builder__layout:     # Where do we get them from? This `components` field comes from us. We use prepareRow to set it.     source: components     # We need a custom plugin to correctly map this.     plugin: layout_builder_sections_pages

The source for where to get the "body" (blocks / SectionComponents for our Section) is this "components" field. That's not a field in my CSV, it's one where I do a lookup to get all the blocks that were migrated in relative to this node. To do this, I use the prepareRow() method provided by migrate_tools to add a new source property.

# Basics about the source plugin - where to get the data, # what kind it is, describe the columns in the csv. source:   plugin: my_pages

View code on GitHub

In this new prepareRow method, we can look up the migrated blocks and return them in the correct order; each will become a section component:

Source Plugin

Now, the components source field is an array of (non-re-usable) block IDs.

Now, we can use that with our custom plugin which is a Migrate API Process Plugin.

Where the Magic Happens

The process plugin has a main entry point of transform(). This method is responsible for returning a value formatted in the way that the destination plugin expects it. In our case, we need to return a Section (or perhaps an array of Sections if you're feeling adventurous). Remember that SectionsComponents primarily make up Sections, we need to first build up the SectionComponents themselves.

To do this, we need access to the UUID generator service in Drupal, and to create a configuration array for the SectionComponent. The following array details the configuration.

  • id: the plugin and derivative you're using, specifically for us "inline_block" and then the bundle, yielding "inline_block:basic" (the type of block).

  • label: what the label of this block is (the block title). This is a required field, so set it to something.

  • provider: layout_builder - always the same in our case.

  • label_display: whether or not to show the label (boolean)

  • view_mode: which view mode to use when displaying this block

  • block_revision_id: the revision ID of the block to display

  • block_serialized: the serialized version of the block (you can probably leave this null and it will be serialized for you later)

  • context_mapping: to be perfectly honest I don't know what this is and maybe someone out there can explain it to me, but it works when it's an empty array :)

After creating your SectionComponents array, you can return a new Section object by specifying the layout you're using for that section, any settings for the Section, and the array of SectionComponents to put into it.

Try it for Yourself!

If you download the example repo, you can restore the included DDEV database snapshot (if using DDEV) or use the .sql file to import the database. You may need to change the paths in your migrations depending on your setup.

As always feel free to be in touch if you would like to learn more!

Apr 19 2021
Apr 19

About you

Did you love taking charge in group projects? Are you always reminding everyone of the deadline? You are a planner through and through. You enjoy piecing together project objectives within the budget and timeline like a jigsaw puzzle, but you enjoy completing a project even more.

When getting to know new people, you excel at quickly building trust and getting them to open up. You understand how to think strategically about the project’s big picture and you can help clients zoom out and see the strategy, too. You’re passionate about what you do and love improving the process for both the team and the client.

About the job

The Digital Project Manager ensures our clients never question whether a project is on track. They manage the scope, timeline, and budgetary constraints to shepherd a project to its successful completion.

The Digital Project Manager is accountable for:

  • Providing regular reporting to clients
  • Managing client expectations around features, delivery time, and budget
  • Establishing internal and external meetings, as needed
  • Maintaining detailed notes for each decision in a project
  • Utilizing an agile system of project management
  • Establishing and using a trusted system to document projects and processes
  • The success of sprint demos
  • Ensuring project plans align with client goals and identifying opportunities for Redfin to suggest improvements or adopt new strategies

The Digital Project Manager is responsible for:

  • Understanding velocity of each project at each sprint
  • Interfacing with client product owners and stakeholders as their primary point of contact from Redfin through the duration of a project
  • Facilitating agile meetings with internal teams and clients, such as user story creation, sprint planning, sprint demos, retrospectives, story pointing, and backlog grooming
  • Verifying that user stories have been appropriately tested for QA
  • Interfacing with Clients, Sales, UX, and other departments to understand the scope of the project being delivered

Requirements and qualifications

  • Ability to work on-site in Portland, Maine
  • Demonstrated experience in proactively and resourcefully solving problems
  • Communicating effectively across teams
  • 3+ years of experience managing projects
  • Familiarity with agile methodologies
  • Passionate about working with a variety of clients and projects
  • Outgoing and persistent
  • Comfortable with digital projects like large-scale websites

About Redfin Solutions

Redfin Solutions, LLC is a web development and design company in Portland, Maine. We conceive, build, and support custom Drupal websites. Our clients include Kripalu, MIT, Harvard, and Dartmouth. Redfin is not just another agency that churns out websites. We have long-lasting relationships with our clients and, hopefully, you. 

We are a Drupal Association partner and help coordinate and sponsor Drupal conferences throughout New England. Our employees are active community members who contribute to the Drupal open source project. Redfin supports professional development opportunities and applicants should be motivated to learn.

Other benefits include: 100% company-paid health insurance premium, HSA company contribution, IRA matching, 4 weeks PTO, 36-hour work week, flexible work schedule, team lunch once a week, standing desk, seltzer & cold brew coffee on tap, annual company retreat, and more.

Redfin Solutions is an equal employment opportunity employer. We celebrate and support diversity for the benefit of our staff and clients, and encourage those from underrepresented groups to apply.

To apply, send send your resume and cover letter to [email protected].

Apr 14 2021
Apr 14

In November 2022, the Drupal community and the Drupal Security Team will end their support for Drupal 7. By that time, all Drupal websites will need to be on Drupal 8 to continue receiving updates and security fixes from the community. The jump from Drupal 7 to 8 is a tricky migration. It often requires complex transformations to move content stuck in old systems into Drupal’s new paradigm. If you are new to Drupal migrations, you can read the official Drupal Migrate API, follow Mauricio Dinarte’s 31 Days of Drupal Migrations starter series, or watch Redfin Solutions’ own Chris Wells give a crash course training session. This blog series covers more advanced topics such as niche migration tools, content restructuring, and various custom code solutions. To catch up, read the previous blog posts Custom Migration Cron Job and Migration Custom Source Plugin.

Most often in Drupal 8, your migration source will be a CSV file, JSON file, or another Drupal database. In some cases your Drupal website needs to coexist in a larger infrastructure. Thankfully, there are various modules for synchronizing Drupal with tools like Salesforce, Bynder, and GatherContent. However, not everything is as clean as those user-friendly modules. This article will dig into migrating data from a Microsoft server using Transact-SQL into a standard Drupal 8 website.

As with any database in Drupal, it starts in the settings.php file. The basic setup for a Transact-SQL database looks like this:

$databases['YOUR_DATABASE_NAME']['default'] = array ( 'database' => '', 'username' => '', 'password' => '', 'prefix' => '', 'host' => '', 'port' => '', 'namespace' => 'Drupal\\Driver\\Database\\sqlsrv', 'driver' => 'sqlsrv', );

“YOUR_DATABASE_NAME” is the key Drupal will use to reference this database, but it does not need to match the actual database name. The other credentials such as database, username, password, prefix, host, and port, need to be filled out based on your specific setup and server, but the last two keys are more general and refer to the type of database.
By default, Drupal uses a MySQL database, so the “driver” field is typically set to “mysql.” However, Drupal by itself does not know how to communicate with a Transact-SQL database, so just setting the “driver” to “sqlsrv” will throw an error

To provide that support, first install and enable the SQL Server module (sqlsrv). But the “drivers” folder in the SQL Server module needs to be accessed at the Drupal root folder (usually called “web” or “docroot”). There are two ways to do this:

  1.  Manually copy the “drivers” folder from the SQL Server module (modules/contrib/sqlsrv/drivers) into the Drupal root folder.
  2. Create a symbolic link (symlink) to the “drivers” folder from the Drupal root folder with a command like this “ln -s modules/contrib/sqlsrv/drivers/ drivers”. The symlink allows the module to update without manual adjustments. 

With the proper credentials and connections, Drupal will now be able to read from the Transact-SQL database.

Now the actual migration can be written. There is no core migration source plugin for this, so you will need to write a custom source plugin that extends DrupalSqlBase. Use Drupal’s dynamic query API to get the database's data, ensuring at least one field can be used as a unique identifier for each row. Once the source plugin is written, the rest of the migration will work as usual.

Mar 11 2021
Mar 11

In November 2022 the Drupal community and the Drupal Security Team will end their support for Drupal 7. By that time, all Drupal websites will need to be on Drupal 8 to continue receiving updates and security fixes from the community. The jump from Drupal 7 to 8 is a tricky migration, often requiring complex data transformations to fit legacy content into Drupal’s new paradigm. If you are new to Drupal migrations, you can read the official Drupal Migrate API, follow Mauricio Dinarte’s 31 Days of Drupal Migrations starter series, or watch Redfin Solutions’ own Chris Wells give a crash course training session. This blog series will cover more advanced topics such as niche migration tools, content restructuring, and various custom code solutions. See the first blog in the series Custom Migration Cron Job.

There are lots of tools built into Drupal 8 (D8) and Drupal 9 (D9) to assist with migrating from a Drupal 7 (D7) website. There is a whole suite of source and destination plugins that allow you to take data from any D7 node, file or user and migrate it into whatever D8 or D9 entity you want. But Drupal can’t account for every single data source you might have, so at some point in your migration you may hit a snag and need to write your own custom migration source plugin. Luckily, Drupal makes this straightforward.

If you don’t already have a custom migration module built, you can follow Mauricio Dinarte’s tutorial. Once you have that set up, go to your custom migration module and create the following nested folder structure for your custom source plugin:

your_custom_module/ ├─ src/ │ ├─ Plugin/ │ │ ├─ migrate/ │ │ │ ├─ source/ │ │ │ │ ├─ CustomSourcePlugin.php

Then create a new PHP file in the source folder.

Now we can write our plugin. If you’ve never written a source plugin before, you can use the d7_node source plugin for reference (this is the Drupal core source plugin for migrating nodes from a Drupal 7 database). Set up your namespace and underneath it add use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;. Then create a class that extends DrupalSqlBase with an @MigrateSource definition commented above it like so:

Note that your class name should be in CamelCase as usual, but the ID should be in snake_case. The ID is how you will reference your source plugin in a migration YAML file.

Inside your custom source plugin, you will need to create four public functions: public function query(), public function initializeIterator(), public function fields(), and public function getIds().

public function query()

Use this to query your source database (such as an old D7 website or whatever external database you are pulling data from). You will build your query using Drupal’s Dynamic Query API. In this example, I have a D7 website that uses an unlimited text field called field_footnote to add footnotes to a node. But in the new D8 website, I want each footnote to be its own entity, while making sure they each stay in the correct order on the correct page. This means I need to process footnotes one by one even though a single node can have several. I also need each footnote to know which node it came from and its order on the page, so the footnotes don’t get scrambled.

To handle this, the query is grabbing the “footnote” text field off all the nodes in the Drupal 7 source database with the entity_id, delta, and field_footnote_value fields selected:

$query = $this->select('field_data_field_footnote', 'f')->fields('f', [ 'entity_id', 'delta', 'field_footnote_value', ]); $query->condition('entity_type', 'node', '='); return $query;

This means that I process my old Drupal 7 field_data_field_footnote table row by row, turning each footnote into its own entity while keeping track of its parent (entity_id), order (delta) and value (field_footnote_value). This can be the trickiest step to get right because the whole source plugin depends on how the data is queried here.

public function initializeIterator()
The initializeIterator function is necessary to run the query and start the iterator. All you need is:

$results = $this->query()->execute(); $results->setFetchMode(\PDO::FETCH_ASSOC); return new \IteratorIterator($results);

If you need to set any constants for the migration, you can do that at this point as well: see d7_file.

public function fields()
The fields function lets you state the queried fields from the source table and provide labels:

return [ 'entity_id' => $this->t('Entity ID'), 'delta' => $this->t('Delta'), 'field_footnote_value' => $this->t('Footnote'), ];

public function getIds()
In the getIds function, you define which data field or fields will be used as unique identifiers. In my footnote example, multiple footnotes can be on the same node, so I need more than just the node ID to uniquely identify them. I also need to add the delta (the footnote’s order on the node).

return [ 'entity_id' => [ 'type' => 'integer', ], 'delta' => [ 'type' => 'integer', ], ];

The entity_id and delta fields will get translated as sourceid1 and sourceid2 respectively in the migrate_map table.

That’s all you need to create your custom source plugin. Now you can write a migration to use it. Remember that in your migration YAML file you will use the @MigrateSource ID that you set in the comment above the class, not the class name.

If you want some extra credit, you can add a fifth public function, prepareRow. This allows you to make data manipulations on each row before it gets sent to the rest of the migration. If I wanted to set a character limit on my footnotes I could use prepareRow to trim or flag any footnotes that are too long. This can also be done as a hook in your module file, hook_migrate_prepare_row.

Feb 25 2021
Feb 25

In November 2022 the Drupal community and the Drupal Security Team will end their support for Drupal 7. By that time, all Drupal websites will need to be on Drupal 8 to continue receiving updates and security fixes from the community. The jump from Drupal 7 to 8 is a tricky migration, often requiring complex data transformations to fit legacy content into Drupal’s new paradigm. If you are new to Drupal migrations, you can read the official Drupal Migrate API, follow Mauricio Dinarte’s 31 Days of Drupal Migrations starter series, or watch Redfin Solutions’ own Chris Wells give a crash course training session. This blog series will cover more advanced topics such as niche migration tools, content restructuring, and various custom code solutions.

There’s a certain leniency afforded to migrating content from an old Drupal 7 website to its new Drupal 8 rebuild. Preserving old content with all its outliers can be complicated and tedious. However, it is typically run only once in production then augmented and completed. Take notes for future migrations and move on. This leniency is not available for ongoing migrations that need to be run routinely to keep a website’s content up to date. This can be anything from a website's directory to up-to-the-minute news and events data where the data comes from outside the website and requires a custom migration. Here the code needs to work consistently and report errors gracefully.

To run these migrations on cron, there are a few different options. The easiest is to use a module like Migrate Cron Scheduler or Migrate Cron. Both of these allow you to quickly pick a custom migration to run on cron and choose its frequency. Migrate Cron Scheduler, however, allows the user to configure the “update” and “sync” flags on the migration import.

The "update" flag will update all previously imported entities. The "sync" flag will also remove any previously imported entities that are no longer in the source database, so that the source and destination are synchronized.

These modules also let you choose a migration group, so that the migration import will automatically respect migration dependencies. The downside is that any custom code that needs to be run in conjunction with the migration will have to be split into a different cron job, and there is no setting on these modules to run the migration at a certain time of day or at an irregular frequency.

For situations that require these additional features, install and configure the Ultimate Cron module. This is a powerful tool that can be used to fine-tune any cron job to an exact time and frequency. The combination of Ultimate Cron and a migration cron module will cover the majority of use-cases. However, if custom code or reporting is necessary immediately before or after the migration runs, then a custom cron job may be needed. To build this, go to your custom migration module and create a hook_cron function in the .module file. This file will need to use the following classes:

use Drupal\migrate_tools\MigrateExecutable; use Drupal\migrate\MigrateMessage; use Drupal\migrate\Plugin\MigrationInterface;

Exactly how you configure this hook will depend on your situation. For each migration that you want to run on this cron job, you will need to follow these steps. First create an instance of the migration plugin by feeding the migration’s id into the Drupal plugin manager: $migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id);

Next, check the status of the migration. Often if there is an error, the migration will be hung in the “importing” state. Running a migration with the “importing” status will result in an error. To get around this, check the status and if necessary reset it to idle:

// Reset migration status. if ($migration->getStatus() !== MigrationInterface::STATUS_IDLE) { $migration->setStatus(MigrationInterface::STATUS_IDLE); }

At this point there are a couple options. You can leave the migration as-is and run a straight import where the content that has already been migrated will remain the same and any new content will be imported. Or set the “update” flag so that new content will be imported and existing content will be updated to match the source: $migration->getIdMap()->prepareUpdate();

Additionally, you can set the “sync” flag to remove any migrated content that no longer exists in the source database (e.g. an event that was cancelled). Note that this option requires at least migrate_tools version 5.

$migration->set('syncSource', TRUE);

Finally, create the MigrationExecutable plugin and run the migration:

$executable = new MigrateExecutable($migration, new MigrateMessage()); $status = $executable->import();

The “status” variable indicates whether the migration ran into any errors. If the status is empty, then there was an error and we can send a report and make custom adjustments to help the migration fail gracefully. Otherwise the migration ran fine.

Once the cron hook is ready, go to the Ultimate Cron jobs page (/admin/config/system/cron/jobs) and click the “Discover jobs” button. Your custom cron job should show up in the table, and you can click the “edit” button to fine-tune the exact timing. For updating or syncing migrations with hundreds of entities, the page may timeout if you manually hit the “run” button for your custom cron job. However, Ultimate cron version 2.x adds the drush commands cron-list and cron-run. Use cron-list to find your cron job id. Then use cron-run with that id and the “--force” flag to manually run your cron job for testing.

The Migrate Cron Scheduler or Migrate Cron module route is much faster to set up and is the better choice for quick, simple migrations that need to be run on the hour. However, for bigger, more complicated migrations that require additional code either immediately before or after the migration, or need to be run in the middle of the night, the Ultimate Cron module combined with a custom cron job provides the most customization and flexibility.

Jan 19 2021
Jan 19

As a designer and front-end developer, the infamous designer-developer handoff has often been between me and myself. Having spent a lot of time in both roles, as well as having worked closely with other designers and developers, I’ve learned a few practices that help me to answer developer questions right from the start.

Responsive Design

The first question to think about in the visual design stage is how a design will translate from a static idea to something people will use. In the real world, people are using all kinds of devices to interact with a website. There are a number of different use cases to think about here. For example, mobile users may be accessing a webpage without internet access, making an autoplaying video a concern for data usage. However, the most common and notable case to think about here is simply different screen sizes.

It’s pretty common to see mobile, tablet, and desktop designs handed off to a developer. If done well, these are generally enough for defining most of a website. Developers usually are working from 320px up, so it’s important to create mobile mockups at this size. From there we widen the browser to make sure the website still looks correct at the sizes in between what was provided in the mockups. The design for the mobile will be applied all the way up to one pixel below tablet size, and the tablet design will be applied up to one pixel below desktop (you may want to specify this for your developer).

For the most part, we want a consistent experience for each of these devices. If, for example, a user opens the website on an external monitor instead of their laptop, it shouldn’t look like a different website. That said, with some layouts the right breakpoint (browser width at which a component changes) is not right at one of the defined device sizes. As you’re designing, check if any of your components or page layouts need to switch at a more specific browser width. A good test of this is to create an artboard that’s a tiny bit smaller than tablet, and put everything in the mobile layout at that width. If anything looks off, consider defining a different breakpoint for that particular component.

Another case to consider is when the website gets extra wide. The last thing you want is to present the final website to your stakeholders and find the components in disarray on a big TV. Generally I’ll define up to two widths for this. One is the content maximum width, and the other is the website maximum width.

The content maximum width of a website is the most amount of space the components take up.The content maximum width of a website is the most amount of space the components take up.

The content maximum width is the size at which the components (such as text or an image) on the website stop increasing in width but the backgrounds (such as a background color or image) keep going. If your content maximum width is particularly large, keep in mind how all your components look stretched to that width. For readability and accessibility of any text on the website, remember that optimal line length is 45-75 characters. 

This width may be all you need, but you can also define a website maximum width if you want something like an image background or full width slideshow to stop growing at a wider point. This may just apply to those full width components that are using images, or (less common in modern design) to the whole website. When deciding on whether or not full width components should keep stretching infinitely wide, think about how you want images to look on very large screens. Unless it’s a background image that is matching the height of that component, the wider an image gets, the more vertical space it will take. Also consider if you want large images to look clear at very large sizes or load quickly at normal and smaller sizes. Limiting the width an image component can reach is one way to strike a balance.

The website maximum width is the most space the design of the website can grow to.The website maximum width is the most space the design of the website can grow to.

One last thing to define is the padding on the sides between tablet and desktop. When the width gets close to your content maximum width, how much padding stays on the sides as the content begins to shrink? I usually leave 16px between mobile and tablet, and 32px between tablet and the content maximum width (technically the content maximum width plus 64px so I don’t lose the padding too early).

Other common responsive considerations are typography and hover states. For typography, you’ll likely want to define heading sizes for mobile, tablet, and desktop. Also pay attention to line height, as well as spacing above and below a heading. For hover states, just remember that a mobile or tablet user can’t hover, so make sure none of the functionality is lost because of this.

Other tips

This covers most of the important points to keep in mind, but here are a few others:

Try to use a consistent base for sizing, preferably based on the body text size. I usually make my base font size 16px and then try to make typography and spacing stick with multiples of 4px.

Never type with caps lock. Always type in lower or sentence case and use your design software to transform the text to uppercase. This will help if you need to change that style without having to retype, and it allows developers (depending on your method of sharing designs) to copy and paste your text rather than retyping it. It also can be a good reminder to the developer that they should be using css to make text uppercase for accessibility (screen readers read text typed in all caps one letter at a time).

Make sure your images and text are flexible. If you have an image that perfectly lines up with the text overlaying it, be aware of how that component might be used and if the content editors will be changing the image or text. Similarly, be aware of the amount of text a content editor might add to any component. Character counts can always be limited, but it won’t hurt to supply that or show how the component should respond to having more text, especially if that text area is highly dependent on browser width.

Loem ipsem call to action exampleLoem ipsem call to action example

One thing that can be easily overlooked is hover and focus states for any interactive elements of your website. For a website to be accessible, it has to be navigable with a keyboard. Focus states are what you see if you tab through a page, and if the difference isn’t notable it will be difficult to do this. Often, hover and focus states can be the same, but there may be some cases where you want to separate them. A form, for example, is an important place to have focus states defined, but you may not need hover states to work the same. Focus states that aren’t specified will generally be automatically provided by the browser, resulting in different appearances between browsers.

One last thing to establish while working with developers is a shared language. A paragraph or a block may mean something different to you as a designer then to a developer working in a content management system. Work together to make sure you have a common understanding of what some of these terms mean. A design system, or even a component library, is a great way to document this. We usually use Invision DSM to share a design system between designers and developers.


To review, remember the following things as you’re designing:

  • Design mobile at 320px
  • Define a content and website maximum width
  • Create font styles for mobile, tablet, and desktop
  • Use a consistent base for sizing, based on your body text size
  • Get in the habit of using your UI to transform your text to uppercase
  • Make images and text flexible whenever possible, and show components with varying amounts of content
  • Provide hover and focus states
  • Establish a shared language

When working with developers, it’s important to keep in mind the gaps between design and development when creating a website. While small design details may be obvious to you, a developer may be less aware of pixel distances and small color variations, focused instead on building the website in the best way possible. Ideally, design handoff is not one moment in a months long process, but a continual collaboration. Getting developer feedback while in the design process can save you from wasting time going down an unfeasible pathway, and getting across clear design patterns can ensure a developer makes the right assumptions from the beginning. Understanding a little of each other’s world can help make the whole process a lot smoother.

Sep 18 2020
Sep 18

Accessibility isn’t just a concern for web developers. With content being dynamically created, there are a few points content editors can keep in mind to make sure their content is accessible to everyone. Following accessibility standards helps non-visual users, but can also help all users find and understand the information they’re looking for.

Creating Emphasis

One of the most common times accessibility issues pop up is when content editors are trying to emphasize sections of text. It is important to keep in mind that screen readers do not recognize details like different colors or bolded text, but will intonate exclamation points. If it is vital to the understanding of the content that a certain sentence be highlighted, consider using an exclamation point. If it is not vital but may help visual users to better understand the message, your best bet is making use of bold. 

From a usability standpoint, be wary of using color for emphasis. Colors can have unintended implications, such as causing the user to think the text is a warning, or even a link. Text also has to pass a certain color contrast ratio with its background to maintain accessibility, so unless a designer or developer with a knowledge of accessibility has picked out new colors for you, it’s best not to introduce more.

Another common mistake when emphasizing content is using all uppercase letters. A screen reader will read this out like an acronym, which could be particularly painful for a full sentence. Aside from screen readers, it is also shown to be less readable for all users when there are more than one or two words in a row in all-caps. Sometimes you’ll see all-caps used on buttons or labels, but the crucial difference is that these are (or should be) made into all-caps with code. A screen reader will usually ignore the css and see the text as it is originally written.

Is bold not enough variation for your content? Talk to your designer or developer about coming up with additional text styles for you to use. You may think to yourself, “I already have a dropdown with five different text styles I can use!” What you’re probably referring to is the heading selector.

Dropdown heading selector menu in a Drupal toolbar.Dropdown heading selector menu in a Drupal toolbar.Heading selector in a WYSIWYG field in Drupal.

Headings should never be used for emphasis or a stylistic choice. They are a tool to add structure to a page.

Heading Structure

Headings are pieces of HTML that are used to give structure to a page. They make it possible for non-visual users to navigate and understand a page without needing to see visual indicators. There is a specific way headings need to be arranged on a page. 

Headings are nested, just like you would see in an outline of a paper where subsections are indented and have a different bullet point or character. Heading 1 is the topmost level, functioning as the title of the page. There should only ever be one H1 on a page, and if you’re using Drupal or any other content management system, the H1 is probably already generated for you as the page title. If you’re working in a body field, for example, you’ll most likely start with H2 to title a section of content. Anything else at this same section level will also be an H2. If you need to label sections within this section, you can start to use H3’s. If you need to go any deeper than this, you can start to use H4’s, H5’s, and H6’s, but if you are going this deep into the structure, it may become difficult to follow for your average user. Here’s an example of heading structure:

(H1) The Most Amazing Chocolate Cake

          (H2) My Grandmother’s History

          (H2) Ingredients

                    (H3) Types of flour you can use

                    (H3)  Alternative ingredients

                              (H4) Vegan alternatives

                              (H4) Gluten free alternatives

          (H2) Instructions

                    (H3) The cake

                    (H3) The frosting

An important thing to watch out for is that heading levels don’t skip. You don’t want to go from an H2 right to an H4. That makes it more difficult for non-visual users to understand the structure of the page, and creates inconsistencies for all users. If you keep finding yourself tempted to do this for visual reasons, think about why it feels like the heading style available doesn’t fit, and work with your designer to figure out how best to fix it.

As mentioned before, don’t use headings simply to emphasize text. If you’re making a whole sentence into a heading, it’s probably not the right use. Headings are also not designed to be used for long sections of text. Bigger and bolder does not always mean easier to read. Sometimes a pull quote or a custom text style is an option that will accomplish what you’re looking for, without creating accessibility and usability issues, as well as design inconsistencies between different content editors.

Foreign Languages

Sometimes on your site you’ll need to add text in a different language. Visual users can identify when they won’t be able to read something, but screen readers need a hint that a sentence is in a different language. There’s a simple way to add this hint to your text: the language button. When you add content to a text field, usually you will have a toolbar at the top that allows you to make things bold, add a link, etc. One button that you may see if you’re using Drupal looks like this:

Language button selector in Drupal tool bar. Language button selector in Drupal tool bar. Language button on a WYSIWYG field in Drupal.

If you see this button, you can highlight your text and select from the dropdown. If you don’t see this button, or any buttons, ask your developer to make it available for that field.

Another thing to note with foreign languages is that users can use external tools to translate the content into a language they understand. For this reason, it is best to stay away from made up words that would only make sense in the language you’re writing, but not others (i.e. “hangry”).

Special Characters

One more content writing trend to avoid is replacing letters with characters, for example “$ave ₵ash” or “see u l8r.” This causes predictable issues for translation and screen readers, but it also can show up incorrectly for anyone. If you have an article titled “$ave ₵ash” it will show up in the url as something like this: yoursite.com/news/ave-ash, which could lead to some confusion when sharing links. The “u” in “see u l8r” would most likely be understood by a non-visual user, but would be impossible to translate.

Writing Accessible Links

Writing good link titles is important, and once you understand how non-visual users navigate a page, it’s easier to accomplish. These links could be inline links, such as a word in a sentence, or could stand alone, such as a button. Regardless, what you want is for link titles to be able to stand on their own. This is because one navigational tool that assistive technology provides users with is a list of links that appear on the page. Imagine a list of links that says “click here,” “learn more,” and “download.” These links don’t give the user any context or information about where the links will go. Instead, create links with text that gives users an understanding of what exactly that link will be doing. No user wants to waste time clicking on a link gives them an unexpected result.

W3.org gives these as examples of successful links (URI refers to the link destination):

A link contains text that gives a description of the information at that URI

A page contains the sentence "There was much bloodshed during the Medieval period of history." Where "Medieval period of history" is a link.

A link is preceded by a text description of the information at that URI

A page contains the sentence "Learn more about the Government of Ireland's Commission on Electronic Voting at Go Vote!" where "Go Vote!" is a link.

Meaningful link text also helps users tabbing through a page from link to link. Users can more easily navigate and determine where to go next without spending more time than wanted on an intermediary page.

Learn more about link accessibility at w3.org.

Writing Good Alternative (Alt) Text

Images that you add to your page need good alt text. When using a content management system, you’ll see a field show up when you add an image, asking for alt text. Alt text allows non-visual users to get the same basic information that the image is giving to a visual user. It is what shows if an image doesn’t load, whether because of a broken image link(?) or a user’s limited internet access. It also provides information to search engines.

Writing good alt text can feel a bit tricky at first. What you want is for your alt text to communicate the content and function of the image. Think of alt text as what you would want to appear in the place of the image if you couldn’t use it. You’ll want to be succinct in describing the image, and avoid any redundancy with the text around it. Screen readers will know that it’s an image, so don’t add text like “image of…” Think about what information is and isn’t helpful, and why you’re adding an image in the first place. Is it just to take up space next to text, or is there something important being conveyed through that image? An image of students on a quad conveys information about student life at the university, whereas a cartoon image of a backpack likely doesn’t add any information.

Required alternate text will have a red asterisk next to it.Required alternate text will have a red asterisk next to it.Example of an alt text field in Drupal8.

Sometimes the alt attribute of an image should be empty. The alt attribute is the piece of HTML that is holding the alt text you enter when you first add an image. You may instead have a label below your image that is visible to all and acts as alt text. You wouldn’t want a screen reader to read out what would ultimately be the same text twice, so you’ll want an empty alt attribute on the image. The only instance where you want no alt text at all is when an image is only decorative, such as a swirling line between text sections or a generic image added only to break up the text (like the previous backpack example). Alternative text may be a required field when you add an image, in which case adding empty alt text by typing a single space in the field might work for you. If this doesn’t work, you may want to talk to a developer about making alt text optional. Consider how many content editors your site has, and if they all have accessibility training. If it is possible that a lot of images that need alt text could end up without it, it may be best to keep it required and minimize using images that don’t add meaning to a page. If the image has alt text in a caption already and you need to add something into the alt text field to be able to save it, try to add context that isn’t already clear from the caption. In most cases you will want alt text anyway, but ask yourself if the alt text you’re adding will be a help or an unnecessary hindrance to a non-visual user.

Wikipedia article with image captioned, Wikipedia article with image captioned, Wikipedia shows the alt text below the image and the alt attribute stays empty.

When an image is linked, and is the only thing in the link, the alt text needs to describe the function of the link. This is because the link doesn’t have any other text in it, so any clue as to where the link is going to go is taken from the alt text. In this case, you can write alt text as if you were writing link text.

For some great examples of how to write alt text, take a look at the list provided by webaim.org.


Once you understand how different users are experiencing your content, writing with accessibility in mind starts to get easier. It’s not always the most exciting and creative part of writing content, but it can be a rewarding experience to continually remind yourself to think about users that often can be overlooked. Putting yourself in someone else’s shoes can help build empathy and make the web, and particularly your piece of it, a more positive space for all.

Jun 19 2020
Jun 19

In response to the COVID-19 pandemic, the Redfin Solutions team has shifted to working remotely. Because of the nature of the pandemic, some of our clients have tight deadlines in order to get information out to people as quickly as possible. A recent client with a special need for a quick turnaround is the Rural Aspirations Project, a non-profit in Maine committed to connecting parents and educators with resources, support, and networking opportunities provided by trusted local organizations. When the schools closed, parents and educators’ need for help grew exponentially. 

Rural Aspirations came to us with the idea for Community Learning for ME. The goal of this project was to create a tool for educators and families to find reliable resources specific to their needs. We knew that for this to be successful it was crucial to keep our focus on the user. At the same time, we had to finish the project within two weeks, including design and implementation, all while adjusting to the new normal of remote work.

User personas + User journeys

Our first step was to get acquainted with the user audiences. Luckily, those at Rural Aspirations are very connected with who their users are, as they work with them personally. In their documentation for the site, they had already included a mix of what we refer to as user personas and user journeys. These outline rough groups of people who will use the website, and the situation they might be in at that moment. 

One of our user personas was Caitlin, a mom of two kids, one in second grade and one in eighth. Her partner is an essential service worker and she has a job where she has to be in meetings during the day. She is overwhelmed by work and childcare but wants to help her kids more. 

Each persona allows the Redfin team to understand a little bit more about one type of person that might be using the site including basic information, the challenges they face, and their goals. We also wanted to understand how they might be using the site – the user journey. For instance, when Caitlin uses this site she wants to get to content for her kids quickly (she may be minutes away from an important meeting) and not have to spend time figuring out if it’s safe and quality content. She would also benefit from discovering that there are resources to help her, in case she wanted to come back when she has some time.

Example of user personaExample of user persona


User flow

Once we started wireframing (the first step in the design process where we map out different pages the website will need), we decided we needed to look at the user flow. The main difference between a user journey and a user flow is that the user flow takes a closer look at how the user interacts with the product once they are on the website. We looked at the main entry points of the website: the homepage and an individual resource, taking into account the possibility of these resources being shared on social media. The challenge was to orient the user, and then create a balance of quick access and discovery. We provided several paths from the homepage to the end goal of finding a resource, and included those filterable resource landing pages as the primary links in the global navigation. From an individual resource, we provided a link back to the filter landing page in order to create a loop from the filtered page to the different resources until the user found the right one for them.

User journey mapUser journey map


Wireframes, annotated designs, and building in Drupal

One of the user personas that Redfin Solutions always anticipates is a content editor, so we kept the user experience in mind even while building the administrator side of the website. We used Drupal to create a content editor experience focused on clarity and ease-of-use, as well as automation, so that Rural Aspirations could focus less on updating the website and more on their jobs. We also gave contributing organizations the ability to add and update their own resources, making use of Drupal’s user permissions to limit them as needed.

One aspect of this project that made it successful was having key members of the team included in every step. We started meeting with our clients with a lead developer, a designer, and a project manager. Later in the building process we would involve others, but having both a design and technical architect from the beginning and throughout the entire project was crucial. It ensured we didn't waste time designing features that couldn’t be built in time, and that features were prioritized and adjusted based on the users’ needs.

The Redfin team was also able to test out some of our design processes and add new ones to make the most of remote collaboration. We used Invision to annotate and share designs, and we tried out Invision’s live whiteboard tool Freehand for the first time to create and share wireframes. Since we’re used to working together on a whiteboard at the office, this helped us to avoid designing in isolation and get quick feedback from each other.

Rural Aspirations’ main concern is helping people through this stressful and overwhelming time. As we worked on this project we realized the logic of sorting through these resources would be complex, but that its success would depend on making it all look simple, thus removing any extra stress from the user. With more time to spend on this project our next step would be to test the success of this tool with google analytics and live user testing, but for now we have created calls for feedback throughout the site. In times of crisis it is particularly important to focus on users first and building sites that relieve burdens.

Mar 26 2020
Mar 26

First, I want to thank everyone in the Drupal community for all you have done in the past to support each other and the Drupal project. I was fortunate when I started my Drupal journey back in 2011 to have been introduced to and embraced by the Drupal community right from the start. I have met so many incredible people who I now consider friends. My life wouldn’t be what it is today without so many of you. Thanks to the awesome community for that.

As one of the community-elected members of the Drupal Association Board of Directors, I am reaching out to the Drupal community for your support.

Please start by taking a few minutes to read the recent post by Dries Buytaert (founder and project lead of Drupal) and the recent post by Heather Rocker (Executive Director of the Drupal Association) regarding the uncertain times which the Drupal Association faces with DrupalCon Minneapolis due to the COVID-19 pandemic. These posts explain why it is so important for folks to step up now and help support the Drupal Association.

So how can the Drupal Community help?

What can an organization do?

What can an individual do?

What can everyone do?

  • Reach out to companies and organizations that you support that depend on Drupal and encourage them to join the Drupal Association as a Supporting Partner or to make a Donation. So many great organizations depend on Drupal for their websites and functionality, yet do not know that the Drupal Association exists or understand why supporting the DA is so important to the Drupal project.  (Template to potentially be used as a starting point for your email)
  • Reach out to those in your local Drupal communities to encourage folks to learn about how the Drupal Association supports the Drupal project and why it’s important for everyone in the Drupal Community to help the Drupal Association during these uncertain times.
  • Share this message on social media to help us reach as many folks as possible.

Thanks to all the incredible folks in the Drupal Community for your help. I look forward to seeing everyone online for now and can’t wait until we can meet in person once again. Stay safe and healthy!

Leslie Glynn
Drupal Association At-Large Board Member
Drupal.org - leslieg

Mar 18 2020
Mar 18

The Drupal 8 core Views module is a big part of why Drupal 8 websites work so well. It takes advantage of Drupal’s structure to create features from recommended content to directories and search pages. However, you can quickly run into complications when implementing a view, especially if your website is multilingual. So get ready to learn how to display multilingual Drupal 8 views of entities (such as nodes, media, and taxonomy terms) as well as entities indexed through the Drupal 8 Search API module.

Use case

A multilingual Drupal 8 website with these guidelines:

  • the default language is English
  • users can choose to view the site in French or Spanish regardless of available translations
  • if an entity does not have the requested French or Spanish translation, then display the English version

What could go wrong with multilingual Drupal 8 views? It starts with how views get data and how translations are stored in Drupal. The database contains separate rows for each translation of an entity, so when the view queries it without specifying a language, it can return duplicates of the same entity. However, if you filter by the page’s interface language, the database will only return entities translated in the page’s language. Additionally, if this is a view of indexed entities, then the language rendering options which fix the above issues are not available. Because of this discrepancy, regular entity views and indexed entity views need different solutions.

Regular entity views

If you are unfamiliar with adding a filter to a view, check out these instructions from drupal.org.

1. In the view edit page, find the Filter Criteria section on the left side under the Fields section. Click Add to get the Filter Criteria pop-up.

2. Next, select Translation Language and click Apply.

3. Then, in the next pop-up, select Site’s default language, and click Apply again.

4. Back on the view edit page in the Language section, click on the setting underneath Rendering Language. 

5. In the pop-up, change the select box to Interface text language selected for page and click Apply.

6. Save your view!

This means that all the entities in your view will display in the requested language, but default to your default language so nothing gets left out. This filter also removes any duplicates, because the language is held constant during the query.

Keep in mind that if any entities in your view do not have a version in the default language, they will not show up, even if the page is set to the language they do have. This was not an issue for the example site as all the content started with English and was later translated, but this could create problems if your content is originating from multiple languages.

Indexed entity views

This was done using version 8.x-3.8 of the Search API Solr module. Since Search API Multilingual Solr Search was not merged into this module until 8.x-2.x, older versions of Search API Solr may not have this functionality (namely the “Language (with Fallback)” field which was added to fix this problem).

1. In the admin menu, go to Configuration > Search and metadata > Search API.

2. Edit the search index your view is pulling from and go to the Fields tab.

3. Click Add Fields.

4. In this pop-up under Global fields, click Add next to Language (with Fallback).

5. Save this configuration and re-index.

6. In your view’s filter criteria, add the Language (with Fallback) field and set it to Interface text language selected for page.

Using multiple languages complicates everything in Drupal, but the Drupal community is always developing patches, updates, and modules to make it easier. If you have a multilingual Drupal website in need of custom solutions, see our contact page to get in touch!

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