farmOS 2.x l10n module #475

This commit is contained in:
Michael Stenta 2022-01-12 06:05:09 -05:00
commit 1439673560
14 changed files with 294 additions and 0 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Localization module (`farm_l10n`) for enabling translations.
- "Other" Structure type
- [Open the Gin toolbar by default #470](https://github.com/farmOS/farmOS/pull/470)
- [Enforce that the changelog is updated with every pull request #469](https://github.com/farmOS/farmOS/pull/469)

View File

@ -0,0 +1,19 @@
# Translating farmOS
This describes how to enable translations in farmOS.
1. Enable the **farmOS Localization** (`farm_l10n1) module.
2. Add your desired language and download translations.
1. Go to Administration > Configuration > Regional and language > Languages.
2. Click "Add language"
3. Select the desired language* and click "Add language".
4. Wait for the language translations to be downloaded and updated.
3. Go to Settings > Language and set the default language, if desired.
4. Individual users can override the default language by editing their profile.
Users that were created before changing the default language will need to be
manually updated to use the new language.
* Note that farmOS has not been fully translated into every language in the
list. To view the status of translations by language, visit
[https://localize.drupal.org/translate/projects/farm](https://localize.drupal.org/translate/projects/farm)
and select the version of farmOS that you are running.

View File

@ -10,6 +10,11 @@ version: 2.x
# automatically selected during installation.
distribution:
name: farmOS
# Set the default language to English.
# We do not allow this default site language config to be changed.
# Instead, we use the "Selected language" detection method to set the default.
# @see https://www.drupal.org/project/farm/issues/3257430
langcode: en
exclusive: true
# Required modules.

View File

@ -57,6 +57,7 @@ function farm_modules() {
'farm_kml' => t('KML export features'),
'farm_import_kml' => t('KML asset importer'),
'farm_fieldkit' => t('Field Kit integration'),
'farm_l10n' => t('Translation/localization features'),
],
];
}

View File

@ -59,6 +59,7 @@ nav:
- Installing: hosting/install.md
- Updating: hosting/update.md
- Email: hosting/email.md
- Translations: hosting/localization.md
- 1.x Migration: hosting/migration.md
theme:
name: material

View File

@ -0,0 +1,9 @@
name: farmOS Localization
description: Enables default configuration for localizing/translating farmOS.
type: module
package: farmOS
core_version_requirement: ^9
dependencies:
- drupal:config_translation
- drupal:language
- drupal:locale

View File

@ -0,0 +1,21 @@
<?php
/**
* @file
* Install, update and uninstall functions for the farm_l10n module.
*/
/**
* Implements hook_install().
*/
function farm_l10n_install() {
// Configure the enabled language detection methods.
\Drupal::configFactory()->getEditable('language.types')->set('negotiation.language_interface.enabled', [
'language-user' => -0,
'language-selected' => 50,
])->save();
// Configure automatic monthly language updates.
\Drupal::configFactory()->getEditable('locale.settings')->set('translation.update_interval_days', 30)->save();
}

View File

@ -0,0 +1,4 @@
farm_l10n.settings:
base_route: farm_settings.settings_page
route_name: farm_l10n.settings
title: 'Language'

View File

@ -0,0 +1,59 @@
<?php
/**
* @file
* Hooks and customizations for the farm_l10n module.
*/
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
/**
* Implements hook_help().
*/
function farm_l10n_help($route_name, RouteMatchInterface $route_match) {
$output = '';
// Help text for the farm/settings/language form.
if ($route_name == 'farm_l10n.settings') {
$output .= '<p>' . t('Select the default language for the user interface. Individual users can override this by editing their profile.') . '</p>';
}
return $output;
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function farm_l10n_form_language_admin_overview_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Disable the ability to change the site's default language and direct users
// to /farm/settings/language instead.
// @see https://www.drupal.org/project/farm/issues/3257430
$message = t('To change the default language of farmOS, please go to <a href=":url">farmOS language settings</a>.', [':url' => Url::fromRoute('farm_l10n.settings')->toString()]);
\Drupal::messenger()->addWarning($message);
foreach (Element::children($form['languages']) as $langcode) {
$form['languages'][$langcode]['default']['#access'] = FALSE;
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function farm_l10n_form_user_register_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Use the "Selected language" as the default for new users (unless it is
// still set to "site_default").
$selected_language = \Drupal::config('language.negotiation')->get('selected_langcode');
if ($selected_language == 'site_default') {
return;
}
if (!empty($form['language']['preferred_langcode'])) {
$form['language']['preferred_langcode']['#default_value'] = $selected_language;
}
if (!empty($form['language']['preferred_admin_langcode'])) {
$form['language']['preferred_admin_langcode']['#default_value'] = $selected_language;
}
}

View File

@ -0,0 +1,2 @@
administer farm language:
title: 'Administer farmOS language'

View File

@ -0,0 +1,7 @@
farm_l10n.settings:
path: '/farm/settings/language'
defaults:
_form: '\Drupal\farm_l10n\Form\L10nSettingsForm'
_title: 'Language settings'
requirements:
_permission: 'administer farm language'

View File

@ -0,0 +1,5 @@
services:
farm_l10n.overrider:
class: Drupal\farm_l10n\Config\FarmLocalizationOverrides
tags:
- { name: config.factory.override, priority: 5 }

View File

@ -0,0 +1,46 @@
<?php
namespace Drupal\farm_l10n\Config;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
use Drupal\Core\Config\StorageInterface;
/**
* Configuration overrides for farmOS localization module.
*/
class FarmLocalizationOverrides implements ConfigFactoryOverrideInterface {
/**
* {@inheritdoc}
*/
public function loadOverrides($names) {
$overrides = [];
if (in_array('system.site', $names)) {
$overrides['system.site']['default_langcode'] = 'en';
}
return $overrides;
}
/**
* {@inheritdoc}
*/
public function getCacheSuffix() {
return 'FarmLocalizationOverrider';
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata($name) {
return new CacheableMetadata();
}
/**
* {@inheritdoc}
*/
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
return NULL;
}
}

View File

@ -0,0 +1,114 @@
<?php
namespace Drupal\farm_l10n\Form;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\language\Form\NegotiationSelectedForm;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Configure the selected language negotiation method for this site.
*
* @internal
*/
class L10nSettingsForm extends NegotiationSelectedForm {
/**
* The entity type manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Constructor for L10nSettingsForm.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager service.
*/
public function __construct(ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($config_factory);
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('entity_type.manager'),
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'farm_l10n_settings_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
// Provide an option to update the default language of existing users.
$form['update_existing_users'] = [
'#type' => 'checkbox',
'#title' => $this->t('Update existing users'),
'#description' => $this->t('Update the language of all existing users to match the default language.'),
'#default_value' => FALSE,
];
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);
// Initiate a batch operation to update the default language of all users
// (except user 1).
if ($form_state->getValue('update_existing_users')) {
$operations = [];
$query = $this->entityTypeManager->getStorage('user')->getQuery();
$uids = $query->condition('uid', '1', '!=')->execute();
foreach ($uids as $uid) {
$operations[] = [
[__CLASS__, 'updateUserLanguage'],
[$uid, $form_state->getValue('selected_langcode')],
];
}
batch_set([
'operations' => $operations,
'title' => $this->t('Updating user languages'),
'error_message' => $this->t('The user language update has encountered an error.'),
]);
}
}
/**
* Update the language for a user.
*
* @param int $uid
* The user ID.
* @param string $langcode
* The new langcode to assign.
*/
public static function updateUserLanguage(int $uid, string $langcode) {
/** @var \Drupal\user\UserInterface $user */
$user = \Drupal::entityTypeManager()->getStorage('user')->load($uid);
$user->set('preferred_langcode', $langcode);
$user->set('preferred_admin_langcode', $langcode);
$user->save();
}
}