admin管理员组

文章数量:1426855

I wanted to know, how do I set CKeditor 5 for RTL? I couldn't find this in thier website.

If it's not possiable, what will be a good editor for rtl?

thank you!

I wanted to know, how do I set CKeditor 5 for RTL? I couldn't find this in thier website.

If it's not possiable, what will be a good editor for rtl?

thank you!

Share Improve this question asked Nov 11, 2017 at 14:20 assafassaf 372 silver badges6 bronze badges 2
  • docs-old.ckeditor./ckeditor_api/symbols/… – BENARD Patrick Commented Nov 11, 2017 at 21:10
  • This is a question about CKE5, while linked docs are for CKE4. – Szymon Cofalik Commented Nov 13, 2017 at 10:12
Add a ment  | 

5 Answers 5

Reset to default 2

I know it's very late answer but in case someone still need this and came to this post :)

using Angular I could achieve it by adding this to CKEditor configs:

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        // This is the part you need regardless
        // of using Angular or not
        language: {
            // The UI will be English.
            ui: 'en',

            // But the content will be edited in Arabic.
            content: 'ar'
        }
    } )

and if you want to use the RTL UI as well just set it as

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        // This is the part you need regardless
        // of using Angular or not
        language: {
            // The UI will be Arabic.
            ui: 'ar',

            // And the content will be edited in Arabic.
            content: 'ar'
        }
    } )

You can find more info about this on CKEditor UI language Docs

I was faced with this problem for 2 weeks and finally, I solved it by coding in ckeditor.js as I experienced, the best way to add the CKEditor 5 ponent, is that first, you should go https://ckeditor./ckeditor-5/online-builder/ and pass 5 easy steps. then you should add it to your project. Also, it is possible to add rtl direction to this build ponent. however, the main problem is that it just adding rtl direction as default and it is not possible to change it during the text as your needs. therefore you have to do some coding by yourself. I did it and it was worked perfectly in Angular 8

if you follow the below steps carefully, the direction selecting will be added to your project easily.

  1. go to @ckeditor/ckeditor5-build-classic/build and open ckeditor.js file

  2. then try to extract it from min js file - you can find too many online tools by googling.

  3. then first you need to find the bellow block code

class Ak extends ok {
        static get requires() {
          return [pk, xk];
        }
        static get pluginName() {
          return "Alignment";
        }
      }

  1. now after this block code you should add the bellow code (just copy it from here to your file)

// Removes the direction attribute from blocks.
      // @private
      function removeDirectionFromSelection(blocks, writer) {
        for (const block of blocks) {
          writer.removeAttribute(DIRECTION, block);
        }
      }

      // Sets the direction attribute on blocks.
      // @private
      function setDirectionOnSelection(blocks, writer, direction) {
        for (const block of blocks) {
          writer.setAttribute(DIRECTION, direction, block);
        }
      }
      const DIRECTION = 'direction';
      class DirectionCommand extends sk {
        refresh() {
          const firstBlock = ck(this.editor.model.document.selection.getSelectedBlocks());

          // As first check whether to enable or disable the mand as the value will always be false if the mand cannot be enabled.
          this.isEnabled = !!firstBlock && this._canBeAligned(firstBlock);
          this.value = (this.isEnabled && firstBlock.hasAttribute('direction')) ? firstBlock.getAttribute('direction') : 'rtl';
        }
        execute(options = {}) {
          const editor = this.editor;
          const model = editor.model;
          const doc = model.document;
          const value = options.value;
          model.change(writer => {
            // Get only those blocks from selected that can have direction set
            const blocks = Array.from(doc.selection.getSelectedBlocks()).filter(block => this._canBeAligned(block));
            const currentDirection = blocks[0].getAttribute('direction');

            // Remove direction attribute if current direction is:
            // - default (should not be stored in model as it will bloat model data)
            // - equal to currently set
            // - or no value is passed - denotes default direction.
            const removeDirection = isDefault(value) || currentDirection === value || !value;

            if (removeDirection) {
              removeDirectionFromSelection(blocks, writer);
            } else {
              setDirectionOnSelection(blocks, writer, value);
            }
          });
        }

        _canBeAligned(block) {
          return this.editor.model.schema.checkAttribute(block, DIRECTION);
        }
      }




      const supportedOptions = ['ltr', 'rtl'];
      class DirectionEditing extends ok {

        constructor(editor) {
          super(editor);

          editor.config.define('direction', {
            options: [...supportedOptions]
          });
        }

        init() {
          const editor = this.editor;
          const schema = editor.model.schema;

          // Filter out unsupported options.
          const enabledOptions = editor.config.get('direction.options').filter(isSupported);

          // Allow direction attribute on all blocks.
          schema.extend('$block', { allowAttributes: 'direction' });
          editor.model.schema.setAttributeProperties('direction', { isFormatting: true });

          const definition = _buildDefinition(enabledOptions.filter(option => !isDefault(option)));

          editor.conversion.attributeToAttribute(definition);

          editor.mands.add('direction', new DirectionCommand(editor));
        }
      }
      function isSupported(option) {
        return supportedOptions.includes(option);
      }
      function _buildDefinition(options) {
        const definition = {
          model: {
            key: 'direction',
            values: options.slice()
          },
          view: {}
        };

        for (const option of options) {
          definition.view[option] = {
            key: 'style',
            value: {
              'direction': option
            }
          };
        }

        return definition;
      }
      function isDefault(direction) {
        // Right now only LTR is supported so the 'ltr' value is always the default one.
        return direction === 'rtl';
      }
      class DirectionUI extends ok {
        get localizedOptionTitles() {
          const t = this.editor.t;

          return {
            'ltr': t('چپ چین کردن متن'),
            'rtl': t('راست چین کردن متن'),
          };
        }

        static get pluginName() {
          return 'DirectionUI';
        }

        init() {
          const editor = this.editor;
          const ponentFactory = editor.ui.ponentFactory;
          const t = editor.t;
          const options = editor.config.get('direction.options');

          options
            .filter(isSupported)
            .forEach(option => this._addButton(option));

          ponentFactory.add('direction', locale => {
            const dropdownView = jw(locale);

            // Add existing direction buttons to dropdown's toolbar.
            const buttons = options.map(option => ponentFactory.create(`direction:${option}`));
            Fw(dropdownView, buttons);

            // Configure dropdown properties an behavior.
            dropdownView.buttonView.set({
              label: t('چپ چین راست چین'),
              tooltip: true
            });

            dropdownView.toolbarView.isVertical = true;

            dropdownView.extendTemplate({
              attributes: {
                class: 'ck-direction-dropdown'
              }
            });

            // The default icon is align left as we do not support RTL yet (see #3).
            const defaultIcon = alignLeftIcon;

            // Change icon to reflect current selection's direction.
            dropdownView.buttonView.bind('icon').toMany(buttons, 'isOn', (...areActive) => {
              // Get the index of an active button.
              const index = areActive.findIndex(value => value);

              // If none of the mands is active, display either defaultIcon or the first button's icon.
              if (index < 0) {
                return defaultIcon;
              }

              // Return active button's icon.
              return buttons[index].icon;
            });

            // Enable button if any of the buttons is enabled.
            dropdownView.bind('isEnabled').toMany(buttons, 'isEnabled', (...areEnabled) => areEnabled.some(isEnabled => isEnabled));

            return dropdownView;
          });
        }


        _addButton(option) {
          const editor = this.editor;

          editor.ui.ponentFactory.add(`direction:${option}`, locale => {
            const mand = editor.mands.get('direction');
            const buttonView = new Ew(locale);

            buttonView.set({
              label: this.localizedOptionTitles[option],
              icon: icons.get(option),
              tooltip: true
            });

            // Bind button model to mand.
            buttonView.bind('isEnabled').to(mand);
            buttonView.bind('isOn').to(mand, 'value', value => value === option);

            // Execute mand.
            this.listenTo(buttonView, 'execute', () => {
              editor.execute('direction', { value: option });
              editor.editing.view.focus();
            });

            return buttonView;
          });
        }
      }
      const alignLeftIcon = '<svg viewBox="0 0 20 20" xmlns="http://www.w3/2000/svg"><path d="M 10 0.199219 C 7.292969 0.199219 5.101562 2.394531 5.101562 5.101562 C 5.101562 7.804688 7.292969 10 10 10 L 10 19.800781 L 12.449219 19.800781 L 12.449219 2.648438 L 14.898438 2.648438 L 14.898438 19.800781 L 17.351562 19.800781 L 17.351562 2.648438 L 19.800781 2.648438 L 19.800781 0.199219 Z M 0.199219 13.675781 L 5.101562 8.777344 L 0.199219 3.875 Z M 0.199219 13.675781"/></svg>';
      const alignRightIcon = '<svg viewBox="0 0 20 20" xmlns="http://www.w3/2000/svg"><path d="M 5.101562 0.199219 C 2.394531 0.199219 0.199219 2.394531 0.199219 5.101562 C 0.199219 7.804688 2.394531 10 5.101562 10 L 5.101562 19.800781 L 7.550781 19.800781 L 7.550781 2.648438 L 10 2.648438 L 10 19.800781 L 12.449219 19.800781 L 12.449219 2.648438 L 14.898438 2.648438 L 14.898438 0.199219 Z M 19.800781 3.875 L 14.898438 8.777344 L 19.800781 13.675781 Z M 19.800781 3.875"/></svg>';

      const icons = new Map([
        ['ltr', alignLeftIcon],
        ['rtl', alignRightIcon],
      ]);
      class Direction extends ok {

        static get requires() {
          return [DirectionEditing, DirectionUI];
        }

        static get pluginName() {
          return 'Direction';
        }
      }

  1. now you need to find "EL.builtinPlugins[....]" code block, then you should add "Direction" to its array.
  2. in your ponent where you added the toolbar items in your ckeditor config you need to add 'direction' in your items(be careful about its word case sensitivity).

congratulation. you will see the direction button now in your toolbar. enjoy

consider confgi prop:

<ckeditor v-model="..." :editor="..." :config="{contentsLangDirection> : 'rtl', language: 'fa'}" />

use fa for persian (farsi) and ar for arabic,

At the moment, RTL is not supported. We only released alpha version for developers preview. RTL is however on our mind and we will support it in the final 1.0.0 release.

Having this occasion, I'd like to ask you what exactly do you mean by "supporting RTL". We need users feedback to be able to correctly prioritize features. Of course, we have our ideas, but we will gladly listen to what interested users would like to see in CKE5.

We'd appreciate any feedback. If you like to, you may give it here or create an issue on our GitHub repository

use this css class that is the builtin ckeditor class.

.ck.ck-editor__editable_inline {
        direction: rtl;
        text-align: right;
    }

本文标签: javascriptUsing CKeditor 5 with rtlStack Overflow