Subscribe to Planet Drupal feed - aggregated feeds in category Planet Drupal
Updated: 6 hours 17 min ago

Specbee: How to manage Google Ads by integrating DFP (DoubleClick for Publishers) with your Drupal 9 website

Tue, 2020/06/30 - 3:03pm
How to manage Google Ads by integrating DFP (DoubleClick for Publishers) with your Drupal 9 website Kiran Singh 30 Jun, 2020 Top 10 best practices for designing a perfect UX for your mobile app

As a publisher, it is especially important for you to get the most of what is offered when it comes to pay-per-click advertising. While selling or buying ads in the ad space can be complex, Google allows granular control over all your ads and configurations through Google Ad Manager. Combine this incredible ad management platform with Drupal 9's easy to use integration methods, and you will be able to manage multiple ads on your site while providing insightful reports for better optimization.

What is DFP?

Google Ad Manager, previously known as Doubleclick for Publishers (DFP) is an ad server which helps the individuals or business with a good number of page views to generate revenue from their pages on the site. This ad platform facilitates both the buying and selling of ads across various ad networks and multiple locations. Google offers its ad server in two variants – Google Ad Manager for Small Business (completely free) and Google Ad Manager 360. It should be noted that the small business offering has some limited features but works well for small to medium-sized businesses.

How to configure Google Ad Manager

1. Creating Ad Units - Ad Units are basic components of the Ad Manager. It defines the size of the ad and specific location of the Ad on your website or app where you want to display the ads.
Below is a sample screenshot of an Ad unit configured on the Ad manager account.

2. Delivering Ad unit - For delivering corresponding add units, we need to add Orders, Line items & Creatives.
•    The Orders in Google Ad manager, where we need to add advertiser & trafficker, in other word we can say if company A wants to buy ad space in our site, the first step to setting them up is to create their order in our google Ad manager account as all subsequent line items within this order.
•    Now create line item which holds information about the specific run dates, targeting, and pricing of one or more creatives.
•    A creative is a specific advertisement, such as an image file, a video file, or other content. One creative can be associated with more than one line item.

How to integrate DFP with Drupal 9

1. First, install and enable the DFP module.
2. Under structure menu, go to DFP Add tags. We have to set Network ID (prepending with “/“ (eg: /111111)  in global DFP settings tab which we will get from the Google Ad manager account. Save the configuration.

3. Fill up the following details in the Add DFP tag form.
   Ad Slot Name → Use the same label of Ad Unit configured in Google Ad manager account
   Size(s) → Copy the same sizes of Ad Unit configured in Google Ad manager account
   Ad Unit Pattern → Copy the exact pattern from the “Code“ of Ad unit configured in Google Ad manager account
  Under “Display Options”, make sure “Create a block for this ad tag“ is checked.
4. Save the Form. This will create a block with the required ad script.
5. Place the Block wherever it is required using either Structure / Block layout (for all pages).

The Drupal DFP integration allows website publishers and builders to integrate their Google ad manager accounts with their Drupal 9 website. To learn more about how we can help you leverage the best of Drupal and its modules, please feel free to connect with us.

Drupal Planet Shefali ShettyApr 05, 2017 Subscribe For Our Newsletter And Stay Updated Subscribe

Leave us a Comment

  Shefali ShettyApr 05, 2017 Recent Posts Image How to manage Google Ads by integrating DFP (DoubleClick for Publishers) with your Drupal 9 website Image Functions and filters to get you started with Twig Tweak in Drupal 8 (with examples) Image An Introduction to Headless or Decoupled CMS in AEM 6.5 Want to extract the maximum out of Drupal? TALK TO US Featured Success Stories

Know more about our technology driven approach to recreate the content management workflow for [24]


Find out how we transformed the digital image of world’s largest healthcare provider, an attribute that defined their global presence in the medical world.


Discover how a Drupal powered internal portal encouraged the sellers at Flipkart to obtain the latest insights with respect to a particular domain.


DrupalCon News: DrupalCon Barcelona 2020 - Experience the Open Web - update

Tue, 2020/06/30 - 9:32am

As Europe starts to reopen its borders, we feel like it’s time to give you an update about where we are now and how you can get ready for the Drupal community fun in the best and easiest way.


Tandem's Drupal Blog: Drupal 7 End of Life and Your Options

Tue, 2020/06/30 - 2:00am
June 30, 2020 A guide to Drupal 7 end of life and your options. The end is near! Drupal 7's official end of life date is November 2022, and if you're one of the over 750,000 Drupal site owners who haven't made the leap to Drupal 8/9, you're probably wondering what the next step for your Drupal 7 site should be. What Does Drupal 7...

Matt Glaman: The new issue forks functionality is going to be awesome.

Tue, 2020/06/30 - 12:42am

This past Sunday I did a livestream where I tried out the new issue forks functionality on The feature is currently beta and project maintainers need to opt-in for the functionality. At the moment you can create a repository fork for an issue, create a work branch, and commit to that branch. You will need to manually create a patch to be uploaded, as Merge Requests with issues are still being worked on (the Drupal Association Infrastructure team is hoping to have this available for DrupalCon Global!)

When you view an issue that supports issue forks, there will be a new block in the sidebar. This allows you to create an issue fork or view information about the existing fork and its branches.

Categories: Blog: Customer Experience, User Experience & Digital Experience: Basics & useful terms

Mon, 2020/06/29 - 10:55am

In this blog post, we’ll take a look at some different terms related to experience in the digital landscape: Customer Experience, User Experience and Digital Experience. We'll explain each of them, discuss the differences and connections between them, and provide a short glossary of useful terms.


Aram Boyajyan: Drupal 8 Commerce add promotion programmatically to the order or shopping cart

Mon, 2020/06/29 - 9:04am
Drupal 8 Commerce add promotion programmatically to the order or shopping cart

Doing this for a particular order is pretty straightforward. All you need to have is the coupon code ID:

superuser Mon, 29/06/2020 - 09:04

The Russian Lullaby: Drupal Migrations (IV): Debugging Migrations-I

Mon, 2020/06/29 - 2:00am

The Drupal migrations, despite their linearity in terms of definitions, contain a lot of inherited complexity. The reason is very intuitive: although the Migrate API is a supersystem that offers a very simple “interface” of interactions for the user-developer who wants to build migration processes, in reality several subsystems work by interacting with each other throughout a migration process: Entities, Database, Plugins…There are a lot of classes involved in even the simplest migration process. If we add the irrefutable fact that a migration will tend to generate errors in …


DrupalEasy: Import and map 800+ lighthouses in Drupal 9

Sun, 2020/06/28 - 6:09pm

Waaaaay back in 2013, I wrote a blog post about importing and mapping over 5,000 points of interest in 45 minutes using (mainly) the Feeds and Geofield modules. Before that, I had also done Drupal 6 demos of importing and displaying earthquake data. 

With the recent release of Drupal 9, I figured it was time for a modern take on the idea - this time using the Drupal migration system as well as (still!) Geofield. 

This time, for the source data, I found a .csv file of 814 lighthouses in the United States that I downloaded from POI Factory (which also appears to be a Drupal site). 

Starting point

First, start with a fresh Drupal 9.0.1 site installed using the drupal/recommended-project Composer template. Then, use Composer to require Drush and the following modules:

composer require drush/drush drupal/migrate_tools drupal/migrate_source_csv drupal/migrate_plus drupal/geofield drupal/geofield_map

Then, enable the modules using

drush en -y migrate_plus migrate_tools migrate_source_csv geofield geofield_map leaflet Overview of approach

To achieve the goal of importing all 814 lighthouses and displaying them on a map, we're going to import the .csv file using the migration system into a new content type that includes a Geofield configured with a formatter that displays a map (powered by Leaflet).

The source data (.csv file) contains the following fields: 

  • Longitude
  • Latitude
  • Name
  • Description

So, our tasks will be:

  1. Create a new "lighthouse" content type with a "Location" field of type Geofield that has a map formatter (via Geofield map).
  2. Prepare the .csv file.
  3. Create a migration that reads the .csv file and creates new nodes of type "Lighthouse".
Create the Lighthouse content type

We will reuse the Drupal title and body field for the Lighthouse .csv's Name and Description fields. 

Then, all we need to add is a new Geofield location field for the longitude and latitude:


Next, we'll test out the new Lighthouse content type by manually creating a new node from the data in the .csv file. This will also be helpful as we configure the Geofield map field formatter (using Leaflet).


By default, a Geofield field uses the "Raw output" formatter. With Leaflet installed and enabled, we can utilize the "Leaflet map" formatter (with the default configuration options).


With this minor change, our test Lighthouse node now displays a map!

Prepare the .csv file

Prior to writing a migration for any .csv file, it is advised to review the file to ensure it will be easy to migrate (and rollback). Two things are very important:

  • Column names
  • Unique identifier

Column names help in mapping .csv fields to Drupal fields while a unique identifier helps with migration rollbacks. While the unique identifier can be a combination of multiple fields, I find it easiest to add my own when it makes sense. 

The initial .csv file looks like this (opened in a spreadsheet):

In the case of the lighthouse .csv file in this example, it has neither column names nor a unique identifier field. To rectify this, open the .csv as a spreadsheet and add both. For the unique identifier field, I prefer a simple integer field. 

Once manually updated, it looks like this:

Create the migration

If you've never used the Drupal 8/9 migration system before it can be intimidating, but at its heart, it is basically just a tool that:

  • Reads source data
  • Maps source data to the destination
  • Creates the destination

Writing your first migration is a big step, so let's get started.

The first step is to create a new custom module to house the migration. First, create a new, empty web/modules/custom/ directory. Then, easily create the module's scaffolding with Drush's "generate" command:

$ drush generate module Welcome to module-standard generator! ––––––––––––––––––––––––––––––––––––––– Module name: ➤ Lighthouse importer Module machine name [lighthouse_importer]: ➤ Module description [The description.]: ➤ Module for importing lighthouses from .csv file. Package [Custom]: ➤ DrupalEasy Dependencies (comma separated): ➤ migrate_plus, migrate_source_csv, geofield Would you like to create install file? [Yes]: ➤ No Would you like to create libraries.yml file? [Yes]: ➤ No Would you like to create permissions.yml file? [Yes]: ➤ No Would you like to create event subscriber? [Yes]: ➤ No Would you like to create block plugin? [Yes]: ➤ No Would you like to create a controller? [Yes]: ➤ No Would you like to create settings form? [Yes]: ➤ No The following directories and files have been created or updated: ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– • modules/lighthouse_importer/ • modules/lighthouse_importer/lighthouse_importer.module

Then, let's create a new web/modules/custom/lighthosue_importer/data/ directory and move the updated .csv file into it - in my case, I named it Lighthouses-USA-updated.csv.

Next, we need to create the lighthouse migration's configuration - this is done in a .yml file that will be located at web/modules/custom/lighthouse_importer/config/install/migrate_plus.migration.lighthouses.yml

The resulting module's file structure looks like this:

web/sites/modules/custom/lighthouse_importer/ config/   install/   migrate_plus.migration.lighthouses.yml   data/   Lighthouses-USA-updated.csv   lighthouse_importer.module

Note that the lighthouse_importer.module, created by Drush, is empty. 

While there are a couple of ways to create the migration configuration, we're going to leverage the Migrate Plus module. 

For more information about writing migrations using code or configurations, check out this blog post from

One of the big hurdles of learning to write Drupal migrations is figuring out where to start. It doesn't make much sense to write the migrate_plus.migration.lighthouses.yml from scratch; most experienced migrators start with an existing migration and tailor it to their needs. In this case, we'll start with the core Drupal 7 node migration (web/core/modules/node/migrations/d7_node.yml)

Let's break up the configuration of the new lighthouse migration into three parts: 

  • Everything before the "process" section.
  • Everything after the "process" section.
  • The "process" section.
Everything before the "process" section

Our starting point (d7_node.yml) looks like this:

id: d7_node label: Nodes audit: true migration_tags: - Drupal 7 - Content deriver: Drupal\node\Plugin\migrate\D7NodeDeriver source: plugin: d7_node

Let's update it to look like this:

id: lighthouses label: Lighthouses source: plugin: 'csv' path: '/var/www/html/web/modules/custom/lighthouse_importer/data/Lighthouses-USA-updated.csv' ids: - ID fields: 0: name: ID label: 'Unique Id' 1: name: Lon label: 'Longitude' 2: name: Lat label: 'Latitude' 3: name: Name label: 'Name' 4: name: Description label: 'Description'

The main difference is the definition of the "source". In our case, since we're using a .csv as our source data, we have to fully define it for the migration. The Migrate Source CSV module documentation is very helpful in this situation.

Note that the "path" value is absolute. 

The "ids" section informs the migration system which field(s) is the unique identifier for each record.

The "fields" section lists all of the fields in the .csv file (in order) so that they are available (via their "name") to the migration. 

Everything after the "process" section

This is often the easiest part of the migration configuration system to write. Often, we just have to define what type of entity the migration will be creating as well as any dependencies. In this example, we'll be creating nodes and we don't have any dependencies. So, the entire section looks like this:

destination: plugin: entity:node The "process" section

This is where the magic happens - in this section we map the source data to the destination fields. The format is destination_value: source_value.

As we aren't migrating data from another Drupal site, we don't need the nid nor vid fields - we'll let Drupal create new node and revision identifiers as we go.

As we don't have much source data, we'll have to set several default values for some of the fields Drupal is expecting. Others we can just ignore and let Drupal set its own default values.

Starting with the just the mapping from the d7_node.yaml, we can modify it to:

process: langcode: plugin: default_value source: language default_value: "und" title: Name uid: plugin: default_value default_value: 1 status: plugin: default_value default_value: 1

Note that we set the default language to "und" (undefined) and the default author to UID=1 and status to 1 (published). The only actual source data we're mapping to the destination (so far) is the "Name", which we are mapping to the node title.

One thing that is definitely missing at this point is the "type" (content type) of node we want the migration to create. We'll add a "type" mapping to the "process" section with a default value of "lighthouse".  

We have three additional fields from the source data that we want to import into Drupal: longitude, latitude, and the description. Luckily, the Geofield module includes a migration processor, which allows us to provide it with the longitude and latitude values and it does the dirty work of preparing the data for the Geofield. For the Description, we'll just map it directly to the node's "body/value" field and let Drupal use the default "body/format" value ("Basic HTML"). 

So, the resulting process section looks like:

process: langcode: plugin: default_value source: language default_value: "und" title: Name uid: plugin: default_value default_value: 1 status: plugin: default_value default_value: 1 type: plugin: default_value default_value: lighthouse field_location: plugin: geofield_latlon source: - Lat - Lon body/value: Description

Once complete, enable the module using 

drush en -y lighthouse_importer

It is important to note that as we are creating this migration using a Migrate Plus configuration entity, the configuration in the migrate_plus.migration.lighthouses.yml is only imported into the site's "active configuration" when the module is enabled. This is often less-than-ideal as this means every time you make a change to the migration's .yml, you need to uninstall and then re-enable the module for the updated migration to be imported. The Config devel module is often used to automatically import config changes on every page load. Note that this module is normally for local use only - it should never be used in a production environment. As of the authoring of this blog post, the patch to make Config Devel compatible with Drupal 9 is RTBC. In the meantime, you can use the following to update the active config each time you make a change to your lighthouses migration configuration:

drush config-delete migrate_plus.migration.lighthouses -y && drush pm-uninstall lighthouse_importer -y && drush en -y lighthouse_importer Testing and running the migration

Use the migrate-status (ms) command (provided by the Migrate Tools module) to check the status of our migration:

$ drush ms lighthouses ------------------- -------------- -------- ------- ---------- ------------- --------------- Group Migration ID Status Total Imported Unprocessed Last Imported ------------------- -------------- -------- ------- ---------- ------------- --------------- Default (default) lighthouses Idle 814 0 814 ------------------- -------------- -------- ------- ---------- ------------- ---------------

If everything looks okay, then let's run the first 5 rows of the migration using the migrate-import (mim) command:

$ drush mim lighthouses --limit=5 [notice] Processed 5 items (5 created, 0 updated, 0 failed, 0 ignored) - done with 'lighthouses'

Confirm the migration by viewing your new nodes of type "lighthouse"!

If all looks good, run the rest of the migration by leaving out the --limit=5 bit:

$ drush mim lighthouses [notice] Processed 804 items (804 created, 0 updated, 0 failed, 0 ignored) - done with 'lighthouses'

If you don't like the results, then you can rollback the migration using "drush migrate-rollback lighthouses" (or "drush mr lighthouses"), make your changes, update the active config, and re-import. 

Next steps

There's a lot more to the Drupal migration system, but hopefully this example will help instill some confidence in you for creating your own migrations. 

The "Leaflet Views" module (included with Leaflet) makes it easy to create a view that shows all imported lighthouses on a single map (see the image at the top of the article). Once you have the data imported, there's so much that you can do!


DrupalEasy: DrupalEasy Podcast 233 - Ashraf Abed (Debug Academy), Drupal news update

Sat, 2020/06/27 - 5:40pm

Direct .mp3 file download.

Ashraf Abed, founder of Debug Academy and talks with Ryan about the Debug Academy's long-form Drupal training. Also, Mike and Ryan take a trip around recent events in the Drupal Community.

URLs mentioned DrupalEasy News Subscribe

Subscribe to our podcast on iTunes, Google Play or Miro. Listen to our podcast on Stitcher.

If you'd like to leave us a voicemail, call 321-396-2340. Please keep in mind that we might play your voicemail during one of our future podcasts. Feel free to call in with suggestions, rants, questions, or corrections. If you'd rather just send us an email, please use our contact page.


Srijan Technologies: Mechanics of Editorial Experience in Digital World vis-a-vis Ergonomics of Manufacturing Industry

Sat, 2020/06/27 - 4:30am

Consider a situation wherein your car indicators are placed near the glove compartment, the horn near the back seat, ignition turn on/off button near the fuel tank, and steering wheel with the button to open the side doors. How infeasible it would be!


OpenLucius: Drupal how-to: redirect anonymous users to login page | A working example module (Drupal 9 compatible)

Fri, 2020/06/26 - 12:07pm

For our Drupal distribution we needed to redirect all anonymous users to the login page, as for now it's implemented as a closed platform for social collaboration. The Drupal 8 way didn't work anymore; we fixed it for Drupal 9 and published a working module. 

So if you're building a Drupal social intranet, collaboration tool or community this might help you to direct them the right way -so they don't get an unfriendly 'access denied'.

Keep in mind that you still have to build the correct access control into all your pages with help of permissions / access checks / advanced route access, this module doesn't provide for that.


Third & Grove: Five Tactics to Generate More B2B Leads with Drupal

Fri, 2020/06/26 - 7:46am

To sell a business a product or service, you have to get in front of the right buyer at the right time. It’s really the second part of that sentence that is so crucial. Why? Because you can’t win deals you don’t know about.


Digital Echidna: Thoughts on all things digital: Adopting open source in the transit and transportation industry

Thu, 2020/06/25 - 6:06pm
The fundamental building blocks of running an efficient and user-focused public transportation network and building a well-designed, effective, and user-centric website are actually pretty similar: You need talented people, quality data, and elite…
Categories: URL shortener integration for a Drupal website

Thu, 2020/06/25 - 5:37pm
Our web agency that creates appealing, feature-rich, and user-friendly websites, shares a post on URL shorteners: what they are, why they are used, and how to integrate a URL shortener with a website. 

Gábor Hojtsy: State of Drupal 9 - first post-release recording from Drupal India Conclave

Thu, 2020/06/25 - 4:58pm

Last week I had the pleasure to present my open source State of Drupal 9 talk at Drupal India Conclave. It was great with very timely questions. While I keep the slides up to date, there is always some new development. Since the recording of this video, Drupal 7's community security support was extended with a year to November 2022. The session should be fully up to date otherwise as of today. Feel free to use the slides to present at your own meetup or in-company training. Thanks Drupal India Association for having me on the program!


Ny Media: Deploying translations in Drupal

Thu, 2020/06/25 - 2:19pm
Deploying translations in Drupal eirik June 25, 2020

One of the things that is remarkable with Drupal 8 (and Drupal 9) is the support for multiple languages. You can translate anything, so making a page completely Norwegian is something Drupal supports out of the box.

If you download Drupal and a couple of modules, you can with just a few clicks have almost all of the interface translated into Norwegian, since translation is a community effort. This means that most of the strings we and our users see during a normal work day, are already translated by us, or someone else in the community. A very special shout out here to svenryen, who almost by himself went through all the strings in Drupal 8.

Today I want to introduce another interesting challenge, and how we are able to solve that with Drupal. Namely deploying new features that should contain translations.

At Ny Media we develop tailored and highly customized solutions for our clients. This way we ensure that their result will make their job and their business easier and more profitable. To do this, we often end up writing custom code for use either between our own projects, or for a specific client.

Translating Drupal Core is a community effort. But brand new strings coming from features that we just created in custom code is not something we can rely on the community to get translated. So we have to do it ourselves. The challenge here lies in how we can get the strings translated on the production site, when the strings are only found in this specific project. Let’s look at a couple of theoretical solutions, and then look at the solution we use. Which we by coincidence think is the best, and now we want to share this with you.

Let’s imagine that we are developing a feature where we display some Copyright information on every page, and we want to translate that. Let’s just say that we call this module “copyright_info”. And maybe we have some code that looks like this:

/** * Implements hook_preprocess_HOOK(). */ function copyright_info_preprocess_page(&$variables) { $variables["page"]["content"][] = [ '#markup' => t('Thank you for visiting this site, and we hope you like the content. However it is copyrighted so please do not steal it.'), ]; }

Now on every page we will have the whole interface in Norwegian. The only exception is the part with copyright, since that is something we just wrote ourselves.

Screenshot from translated frontpage. Note the untranslated custom string. Option 1: Translating “by hand” when the new feature is deployed.

This is the easiest and most obvious way to do it. After you have deployed your new feature, you go into the administration form for your site. This part is located under  Administration -> Configuration -> Regional and language -> User interface translation, or path admin/config/regional/translate. So we search up the string(s) we just made. Then we can translate them one by one.

This is a very transparent and easy solution. And that has its advantages:

  • Requires no additional build steps to import translations
  • Requires no additional modules to enable

However, it has some disadvantages as well:

  • Tedious to do for more than one translation.
  • Error prone (Copy-paste errors, or typos)
  • You end up having a deployed site with a temporarily untranslated string while you are manually editing the translation(s).

In this example case this might be a good solution since we only have that one string. But once you get more than 1 string to translate, you really do not want to do that by hand. And if you have a high traffic site, you probably do not want your site do be untranslated while you work.

Option 2: Exporting translation on a dev/staging site, and importing it on the live site

Another option that is available out of the box, is to export all the translated strings you have on one site, and then import them on another.

First you can export and download the strings from a copy of the site where your new strings are translated. Then you upload and import the strings on the live site

This is also fairly easy to do so it does have similar advantages:

  • Requires no additional build steps to import translations
  • Require no additional modules to enable
  • Supports importing of huge amounts of text

It does however come with some disadvantages:

  • Still manual work, and might leave your site temporarily untranslated
  • Requires manual intervention
  • The translations batches are not version controlled
Option 3: Importing custom translations as a part of your build process.

As you probably have figured, this is the option I wanted to highlight in this blog post, and this is the method we are currently using in Ny Media. To achieve this we use a Drupal module called Custom translation deployments. This is a module we developed as part of a client project, which in turn ended up being our standard setup for deploying translations on our projects.

The module provides two ways of providing translations to easily deploy as part of the build process. We will look at the most simple here, and then briefly mention a slightly more advanced way.

The first step of being able to deploy translations is making sure your translations are committed to your version control system. A default Drupal installation will set the translation directory to sites/default/files/translations,. This is typically a directory ignored by the version control system. So we start this process by changing it to somewhere we can check in to our version control system. Like ../translations. To change it, we go to the page for File system located under Administration -> Configuration -> Media, or at path admin/config/media/file-system.

Since the project is located one level below the Drupal installation, we place the translations in a translations folder in the root of the directory.

Here in Norway we are usually looking for Norwegian translations for our Norwegian clients. The module Custom translation deployments comes with a predefined translation file pattern defined. Meaning if we place a file called project_specifc-custom.LANGUAGE.po (or in the case of Norwegian project_specifc-custom.nb.po) in the newly defined and created translation folder, it will get imported. Let’s try that.

First let's make sure the file is in place.

$ ls ../translations project_specific-custom.nb.po

Now one can either use the interface (under Administration -> Reports -> Available translation updates - admin/reports/translations) or do this with drush.

The other convenient thing is to add this as part of your deployment script. Maybe you have some sort of Continuous Deployment tool for it, or maybe you just use some manual and run it on your server. Whatever boat you are in, you can always do something like this:

$ drush sdel locale.translation_last_checked && drush locale-update && drush cr > [notice] Translation file not found: > [notice] Checked nb translation for project_specific. > [notice] Imported nb translation for project_specific. > [notice] Translations imported: 1 added, 0 updated, 0 removed. > [notice] Message: En oversettelsesfil importert. /1/ oversettelser ble lagt til, /0/ > oversettelser ble oppdatert og /0/ oversettelser ble fjernet.

This is actually 3 commands. The first one makes sure that Drush is forced to think it is time to update the translations. The second one updates the translations, and the third one clears the cache. This third step is important if you have translated strings in your JavaScript.

But it is also possible to do this through the interface. Which would look something like this.

One other thing to note is that having the project defined as a locale project, means you can have a translation file on a server, and Drupal will look for updates to it. As you can see from the drush output above, it will look for it in a specific pattern. This is defined as part of the hook implementation for custom_translation_deployments. So if you want a translation file for your organization you can have a custom module implementing this hook, and therefore also make it available to be updated and downloaded automatically. Her is one such example:

/** * Implements hook_custom_translation_deployments_files(). */ function my_org_custom_translation_deployments_files() { $items = []; $items[] = [ 'name' => 'my_org', 'project_type' => 'module', 'core' => '8.x', // We set the version to something static, but not to "dev". 'version' => 'custom', 'server_pattern' => '', 'status' => 1, ]; return $items; }

This way we can now either ship a translation file called my_org-custom.nb.po or a file on

The last part I would recommend is to only look for translation updates in the local filesystem on your production server, and only manually. This way, Drupal will never try to download new translations on your live site, creating conflicts with your version controlled translations. The setting for this is at  Administration -> Configuration -> Regional and language -> User interface translation -> Interface translation settings, or path admin/config/regional/translate/settings.

You can also do this as part of the settings on the live site, and instead keep this setting on for development sites. To do that in settings.php you would do this:

$config['locale.settings']['translation']['use_source'] = 'local'; Flexible translation methods

However your advanced methods of deployment and translation is, Drupal has a way for you to handle it. And when Drupal out of the box can not support your preferred method of deployment or automation, contributed projects like Custom translation deployments can help you the last steps of the way. The module is fully tested, used in production on many sites, and supports Drupal 9 out of the box!

If you are looking for a partner in developing your localized Drupal site, contact Ny Media!



Axelerant Blog: Our implementation of serverless,

Thu, 2020/06/25 - 2:19pm
Our implementation of serverless, decoupled Drupal enabled a luxury resort client to consolidate their web properties and serve multilingual content to a worldwide audience.

Axelerant Blog: Choosing the right support vendor is a

Thu, 2020/06/25 - 2:19pm
Choosing the right support vendor is a challenging process. Here's how you can tell if your Drupal services provider is right for you.

Axelerant Blog: Drupal 8 developers, making Drupal 8

Thu, 2020/06/25 - 2:19pm
Drupal 8 developers, making Drupal 8 PHP 7 ready is one of the best things to happen for us. This is why.