One of the things a website owner expects when they launch their new Drupal 8/9 website is that their Drupal 6/7 users are still there, and can still log in using the same credentials.

Luckily, the migrate framework and ecosystem makes this very easy for us in Drupal 8 and beyond. However, from time to time a developer might find themselves in a situation where they forgot to migrate something. Like for example the language of the user. This is especially awkward if your site is mainly in one language, and now all of the users are suddenly sent English emails, even if we meticulously translated all emails into the language of the website.

One way to fix this would be to fix the migration and then re-run it. However, if you discovered this after the launch of the new website, your users might have changed their email or their password, and therefore would probably not appreciate it if their changes disappeared. So we need to update the actual language fields instead, keeping the changes in emails and passwords and other fields.

So I was tasked exactly this on a migrated site. Everyone had their language set to English, when the site itself only was selling products to Norwegian customers, and had no English interface. To fix this I wrote this quick script, which I then ran with drush. One way to do that is to save this script as a file called fix-users.php and then run it using the command drush scr fix-users.php. You can also run this piece of code in a devel PHP textfield, or even put it into a post_update hook.

Here is the script, for future reference for myself, and for saving you some minutes if you just had this very problem.

<?php

use Drupal\user\Entity\User;

// This finds all of the UIDs on the site.
$uids = \Drupal::entityTypeManager()->getStorage('user')->getQuery()
  // If you run this script with drush somehow, you need to add this flag to
  // make sure you can load all users, not only the ones you have access to as
  // user id 0.
  ->accessCheck(FALSE)
  ->execute();

// I want to set the language to "nb" for all of the users. "nb" means Norwegian
// - Bokmål. Maybe you want another code?
$language_to_change_to = 'nb';

foreach ($uids as $uid) {
  $user = User::load($uid);
  // User 0 and user 1 are special. Don't change them.
  if (!$user || $user->id() < 2) {
    continue;
  }
  // We change all of these fields, but for different reasons you might want to
  // only change one or two?
  $language_fields = [
    'langcode',
    'preferred_langcode',
    'preferred_admin_langcode',
  ];
  foreach ($language_fields as $field) {
    if (!$user->hasField($field)) {
      continue;
    }
    $user->set($field, $language_to_change_to);
  }
  $user->save();
}

With that out of the way, let's finish this article with an animated gif called "migration".