Issue #2050097 by Gábor Hojtsy, Wim Leers: Map CKEditor languages to Drupal languages.
parent
7e5119cd45
commit
d4b4d27cd9
|
@ -2,3 +2,10 @@ services:
|
|||
plugin.manager.ckeditor.plugin:
|
||||
class: Drupal\ckeditor\CKEditorPluginManager
|
||||
arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler']
|
||||
cache.ckeditor.languages:
|
||||
class: Drupal\Core\Cache\CacheBackendInterface
|
||||
tags:
|
||||
- { name: cache.bin }
|
||||
factory_method: get
|
||||
factory_service: cache_factory
|
||||
arguments: [ckeditor]
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
|
||||
namespace Drupal\ckeditor\Plugin\Editor;
|
||||
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\ckeditor\CKEditorPluginManager;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Language\LanguageManager;
|
||||
use Drupal\editor\Plugin\EditorBase;
|
||||
use Drupal\editor\Annotation\Editor;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
|
@ -27,6 +30,20 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
*/
|
||||
class CKEditor extends EditorBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The module handler to invoke hooks on.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManager
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The CKEditor plugin manager.
|
||||
*
|
||||
|
@ -45,17 +62,30 @@ class CKEditor extends EditorBase implements ContainerFactoryPluginInterface {
|
|||
* The plugin implementation definition.
|
||||
* @param \Drupal\ckeditor\CKEditorPluginManager $ckeditor_plugin_manager
|
||||
* The CKEditor plugin manager.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler to invoke hooks on.
|
||||
* @param \Drupal\Core\Language\LanguageManager $language_manager
|
||||
* The language manager.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, array $plugin_definition, CKEditorPluginManager $ckeditor_plugin_manager) {
|
||||
public function __construct(array $configuration, $plugin_id, array $plugin_definition, CKEditorPluginManager $ckeditor_plugin_manager, ModuleHandlerInterface $module_handler, LanguageManager $language_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->ckeditorPluginManager = $ckeditor_plugin_manager;
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->languageManager = $language_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
|
||||
return new static($configuration, $plugin_id, $plugin_definition, $container->get('plugin.manager.ckeditor.plugin'));
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('plugin.manager.ckeditor.plugin'),
|
||||
$container->get('module_handler'),
|
||||
$container->get('language_manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -191,8 +221,6 @@ class CKEditor extends EditorBase implements ContainerFactoryPluginInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getJSSettings(EditorEntity $editor) {
|
||||
$language_interface = language(Language::TYPE_INTERFACE);
|
||||
|
||||
$settings = array();
|
||||
|
||||
// Get the settings for all enabled plugins, even the internal ones.
|
||||
|
@ -202,13 +230,23 @@ class CKEditor extends EditorBase implements ContainerFactoryPluginInterface {
|
|||
$settings += $plugin->getConfig($editor);
|
||||
}
|
||||
|
||||
// Fall back on English if no matching language code was found.
|
||||
$display_langcode = 'en';
|
||||
|
||||
// Map the interface language code to a CKEditor translation.
|
||||
$ckeditor_langcodes = $this->getLangcodes();
|
||||
$language_interface = $this->languageManager->getLanguage(Language::TYPE_INTERFACE);
|
||||
if (isset($ckeditor_langcodes[$language_interface->id])) {
|
||||
$display_langcode = $ckeditor_langcodes[$language_interface->id];
|
||||
}
|
||||
|
||||
// Next, set the most fundamental CKEditor settings.
|
||||
$external_plugin_files = $this->ckeditorPluginManager->getEnabledPluginFiles($editor);
|
||||
$settings += array(
|
||||
'toolbar' => $this->buildToolbarJSSetting($editor),
|
||||
'contentsCss' => $this->buildContentsCssJSSetting($editor),
|
||||
'extraPlugins' => implode(',', array_keys($external_plugin_files)),
|
||||
'language' => $language_interface->id,
|
||||
'language' => $display_langcode,
|
||||
// Configure CKEditor to not load styles.js. The StylesCombo plugin will
|
||||
// set stylesSet according to the user's settings, if the "Styles" button
|
||||
// is enabled. We cannot get rid of this until CKEditor will stop loading
|
||||
|
@ -227,6 +265,52 @@ class CKEditor extends EditorBase implements ContainerFactoryPluginInterface {
|
|||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of language codes supported by CKEditor.
|
||||
*
|
||||
* @return array
|
||||
* An associative array keyed by language codes.
|
||||
*/
|
||||
public function getLangcodes() {
|
||||
// Cache the file system based language list calculation because this would
|
||||
// be expensive to calculate all the time. The cache is cleared on core
|
||||
// upgrades which is the only situation the CKEditor file listing should
|
||||
// change.
|
||||
$langcode_cache = cache('ckeditor.languages')->get('langcodes');
|
||||
if (!empty($langcode_cache)) {
|
||||
$langcodes = $langcode_cache->data;
|
||||
}
|
||||
if (empty($langcodes)) {
|
||||
$langcodes = array();
|
||||
// Collect languages included with CKEditor based on file listing.
|
||||
$ckeditor_languages = glob(DRUPAL_ROOT . '/core/assets/vendor/ckeditor/lang/*.js');
|
||||
foreach ($ckeditor_languages as $language_filename) {
|
||||
$langcode = basename($language_filename, '.js');
|
||||
$langcodes[$langcode] = $langcode;
|
||||
}
|
||||
cache('ckeditor.languages')->set('langcodes', $langcodes);
|
||||
}
|
||||
|
||||
// Get language mapping if available to map to Drupal language codes.
|
||||
// This is configurable in the user interface and not expensive to get, so
|
||||
// we don't include it in the cached language list.
|
||||
$language_mappings = $this->moduleHandler->moduleExists('language') ? language_get_browser_drupal_langcode_mappings() : array();
|
||||
foreach ($langcodes as $langcode) {
|
||||
// If this language code is available in a Drupal mapping, use that to
|
||||
// compute a possibility for matching from the Drupal langcode to the
|
||||
// CKEditor langcode.
|
||||
// e.g. CKEditor uses the langcode 'no' for Norwegian, Drupal uses 'nb'.
|
||||
// This would then remove the 'no' => 'no' mapping and replace it with
|
||||
// 'nb' => 'no'. Now Drupal knows which CKEditor translation to load.
|
||||
if (isset($language_mappings[$langcode]) && !isset($langcodes[$language_mappings[$langcode]])) {
|
||||
$langcodes[$language_mappings[$langcode]] = $langcode;
|
||||
unset($langcodes[$langcode]);
|
||||
}
|
||||
}
|
||||
|
||||
return $langcodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -309,6 +309,27 @@ class CKEditorTest extends DrupalUnitTestBase {
|
|||
$this->assertIdentical($expected, $stylescombo_plugin->getConfig($editor), '"StylesCombo" plugin configuration built correctly for customized toolbar.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests language list availability in CKEditor.
|
||||
*/
|
||||
function testLanguages() {
|
||||
// Get CKEditor supported language codes and spot-check.
|
||||
$this->enableModules(array('language'));
|
||||
config_install_default_config('module', 'language');
|
||||
$langcodes = $this->ckeditor->getLangcodes();
|
||||
|
||||
// Language codes transformed with browser mappings.
|
||||
$this->assertTrue($langcodes['pt-pt'] == 'pt', '"pt" properly resolved');
|
||||
$this->assertTrue($langcodes['zh-hans'] == 'zh-cn', '"zh-hans" properly resolved');
|
||||
|
||||
// Language code both in Drupal and CKEditor.
|
||||
$this->assertTrue($langcodes['gl'] == 'gl', '"gl" properly resolved');
|
||||
|
||||
// Language codes only in CKEditor.
|
||||
$this->assertTrue($langcodes['en-au'] == 'en-au', '"en-au" properly resolved');
|
||||
$this->assertTrue($langcodes['sr-latn'] == 'sr-latn', '"sr-latn" properly resolved');
|
||||
}
|
||||
|
||||
protected function getDefaultInternalConfig() {
|
||||
return array(
|
||||
'customConfig' => '',
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# Browsers use different language codes to refer to the same languages,
|
||||
# these defaults handles the most common cases.
|
||||
no: 'nb' # Norwegian
|
||||
pt: 'pt-pt' # Portuguese
|
||||
zh: 'zh-hans' # Default Chinese to simplified script
|
||||
zh-tw: 'zh-hant' # Taiwan Chinese in traditional script
|
||||
zh-hk: 'zh-hant' # Hong Kong Chinese in traditional script
|
||||
zh-mo: 'zh-hant' # Macao Chinese in traditional script
|
||||
|
|
|
@ -111,7 +111,13 @@ function language_from_browser($languages) {
|
|||
// so we multiply the qvalue by 1000 to avoid floating point comparisons.
|
||||
$langcode = strtolower($match[1]);
|
||||
$qvalue = isset($match[2]) ? (float) $match[2] : 1;
|
||||
$browser_langcodes[$langcode] = (int) ($qvalue * 1000);
|
||||
// Take the highest qvalue for this langcode. Although the request
|
||||
// supposedly contains unique langcodes, our mapping possibly resolves
|
||||
// to the same langcode for different qvalues. Keep the highest.
|
||||
$browser_langcodes[$langcode] = max(
|
||||
(int) ($qvalue * 1000),
|
||||
(isset($browser_langcodes[$langcode]) ? $browser_langcodes[$langcode] : 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue