Custom languages can be added to any given install by using the "Custom language..." option at the bottom of the language select list on the "Add language" form.

If you add a language using this feature, you will get an added configured language which will be available in the switch language block an which will be listed in /admin/config/regional/language

But how to add a custom language without adding a language for the site?

This is the goal of this feature request.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

DuneBL created an issue. See original summary.

DuneBL’s picture

Here is a patch that solve this issue:

1-Most of the patch is made of a new ConfigEntityBase named "CustomLanguage": it will store the added languages and it will provide forms to edit, update or delete the languages.
I will also provide a list view of the added language at admin/config/languagefield

2-The added languages are merged with the "core" languages with those lines in LanguageItem.php:
a)Adding the custom languages at construct time (stored in $customLanguages):

  protected $customLanguages;

  public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) {
    parent::__construct($definition, $name, $parent);
    $storage = \Drupal::entityTypeManager()->getStorage('customlanguage');
    $lang_ids=$storage->loadMultiple();
    foreach ($lang_ids as $cust_lang) {
      $this->customLanguages[$cust_lang->getLangCode()]=[$cust_lang->label(),$cust_lang->getLangNativeName()];
    }
  }

b)Add custom languages in the options (one line added)

  public function getPossibleOptions(AccountInterface $account = NULL, $format = 'en') {
    $select_options = array();

    // No need to cache this data. It is a hardcoded list.
    $standard_languages = \Drupal::languageManager()->getStandardLanguageList();
    
    //Add the custom languages to the list
    $standard_languages+=$this->customLanguages;
    ....

c)Fix the getNativeName function (one line added)

  public function getNativeName() {
    $standard_languages = \Drupal::languageManager()->getStandardLanguageList();
    $standard_languages+=$this->customLanguages;
    return $standard_languages[$this->value][1];
  }

3-The patch adds also a permission to view, edit, create or delete the custom language: "CRUD languages for languagefield"

4-The patch adds a menu item under "system.admin_config_regional" to see the custom language list

5-The patch adds a schema.yml file to allow the creation of custom languages in the form of yml text files

Let me know if you think that this patch goes in a right direction.

Note: I am not sure the exact process to make this patch working, but here is my idea:
1-Clear the cache (drush cr)
2-Update entities (drush entup)

DuneBL’s picture

I have added 2 more changes in this patch:
1-Add a getLanguage() public function in LanguageItem class

  public function getLanguage() {
    $langcode=$this->value;
    $language=ConfigurableLanguage::createFromLangcode($langcode);
    if (array_key_exists($langcode, $this->customLanguages)){
      $language->set("label", $this->customLanguages[$langcode][0]);
    }
      return $language;
  }

This function is getting the language "the normal way" through createFromLangcode, and if the language code exists in the customLanguages list, it will update the label property with the name of the custom language.

2-Update the FieldFormatter viewValue function:
I change:
$language = ConfigurableLanguage::createFromLangcode($langcode);
into

//Must call LanguageItem::getLanguage to have the benefit of added custom languages
$language = $item->getLanguage();

In other word, I used the newly added function to get the language object

johnv’s picture

Version: 8.x-1.x-dev » 8.x-1.3
Status: Active » Needs work

I have been working on this.
Needs some more work;
- filter_xss on user input.
- no new permission, bu re-use existing field permission. (or not)
- the edit form needs work. The machine name is not correct. I have de-duplicate ID and langcode.

johnv’s picture

Title: Allow custom languages to be added without adding a language to the site » Add custom (disabled) languages

  • johnv committed 6192a58 on 8.x-1.x authored by DuneBL
    Issue #2848356 by DuneBL, johnv: Add custom (disabled) languages
    
DuneBL’s picture

I found a small error in:

  public static function getCustomLanguageList() {
    $storage = \Drupal::entityTypeManager()->getStorage('custom_language');
    $lang_ids = $storage->loadMultiple();
    foreach ($lang_ids as $language) {
      $languages[$language->id()] = [$language->label(), $language->getNativeName()];
    }
    return $languages;
  }

We should add

$languages=[];

Before the foreach in the case there isn't any language enoded.

  • johnv committed 391b5c7 on 8.x-1.x authored by DuneBL
    Issue #2848356 by DuneBL: Add custom (disabled) languages
    
johnv’s picture

Fixed. Thanks.

Can you check my remarks in #4?

jacktonkin’s picture

This is so much better than attempting to override LanguageManager::getStandardLanguageList like I was doing before. Thank-you!

In response to your remarks in #4:

  1. I think form validation can be similarly aggressive to the configurable_language forms in core (see below)
  2. I suppose you could use'administer languages' for the permission since language module is a dependency. Custom languages could be used with fields on any kind of entity so inheriting field permissions would add too much complexity. To be honest I think it's fine for a new config entity to have its own 'administer' permission. Perhaps consider renaming to 'administer custom languages'?
  3. Again, I think the pattern from core's language module makes sense. There the langcode is the entity ID and is not editable. Machine names shouldn't be editable in the UI: if you make a mistake when creating a new language it's a quick one-off action to delete and start over.

The attached patch copies liberally from Drupal\language\Form\LanguageFormBase to address 1 & 3. Marking as needs review for those, I'd be happy to re-roll if you want to change the permission used.

  • johnv committed c8c20a7 on 8.x-1.x authored by jacktonkin
    Issue #2848356 by DuneBL, jacktonkin: Add custom (disabled) language
    

  • johnv committed c059953 on 8.x-1.x authored by jacktonkin
    Issue #2848356 by DuneBL, jacktonkin: Add custom (disabled) languages
    
johnv’s picture

Status: Needs review » Fixed

#11 commits the patch from #10.
#12 reuses core's 'administer languages' permission.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.