eiriksm.dev: Help! All my users were migrated with the wrong language!

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 they are translated 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 launch, your users might have changed their email or their password, and 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 with fixing up this site and its users, now that 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 run 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.

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

<?php

use DrupaluserEntityUser;

// 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, 'nb');
  }
  $user->save();
}

With that out of the way, let’s finish this article with an animated gif called “migration”.