How to easily alter an entity's base field definition per bundle We are using the group module in Drupal 8, which introduces a custom entity "group". This entity features a "label" base field with the title "Title". As groups administrator, you can create several different group types, which are handled as fieldable bundles of the group entity and inherit its label base field.

Depending on the group type, we wish to override the generic label title within forms, views, templates, and so on to e.g. 'Label', 'Name', 'Branch', 'Department', 'Section', ...

However, the group entity does not expose the label title within its config form as the node module does. So we tried overriding the title using hook_entity_base_field_info_alter() like this:

/**
 * Implements hook_entity_base_field_info_alter().
 */
function mymodule_entity_base_field_info_alter(&amp;$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type) {
  if ($entity_type-&gt;id() == 'group' &amp;&amp; !empty($fields['label'])) {
    $fields['label']-&gt;setLabel(t('Name'));
  }
}


Which works, but changes the title for all bundles.

Our next try was hook_entity_bundle_field_info_alter(). It exposes bundle information, but it does not allow for base fields to be altered. Trying to re-add the base field definition with a different title (in order to let the core merge the field definitions and override the base field definitions) caused different run-time exceptions.

So we ended up in manually altering form build arrays and widget titles, which may cause trouble later when the amount of group types is increasing.

How can we alter the base field's title on a per-bundle base without having to extend the group module or manually altering all occurrences of our group entities' field labels?
Bundle specific labels for base fields are stored in label of a BaseFieldOverride config entity:


  Defines the base field override entity.
  
  Allows base fields to be overridden on the bundle level.
  
  Plugin annotation

@ConfigEntityType(
  id = "base_field_override",
  label = @Translation("Base field override"),
  handlers = {
    "storage" = "Drupal\Core\Field\BaseFieldOverrideStorage",
    "access" = "Drupal\Core\Field\BaseFieldOverrideAccessControlHandler",
  },
  config_prefix = "base_field_override",
  entity_keys = {
    "id" = "id",
    "label" = "label"
  },
  config_export = {
    "id",
    "field_name",
    "entity_type",
    "bundle",
    "label",
    "description",
    "required",
    "translatable",
    "default_value",
    "default_value_callback",
    "settings",
    "field_type",
  }
)



When you get a base field from EntityFieldManager::getFieldDefinitions($entity_type_id, $bundle), set a new label for the field and save the field definition, then this label is not stored in the entity type (which would not be possible, because this is in code and the same for all bundles), but in the mentioned base field override.