Browse Source

Creating image2_chamilo plugin for CKEditor #1738

Angel Fernando Quiroz Campos 8 years ago
parent
commit
b0378df4c9
73 changed files with 3815 additions and 0 deletions
  1. 573 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/dialogs/image2_chamilo.js
  2. BIN
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/icons/hidpi/image.png
  3. BIN
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/icons/image.png
  4. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/af.js
  5. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ar.js
  6. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/az.js
  7. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/bg.js
  8. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/bn.js
  9. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/bs.js
  10. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ca.js
  11. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/cs.js
  12. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/cy.js
  13. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/da.js
  14. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/de-ch.js
  15. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/de.js
  16. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/el.js
  17. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/en-au.js
  18. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/en-ca.js
  19. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/en-gb.js
  20. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/en.js
  21. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/eo.js
  22. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/es.js
  23. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/et.js
  24. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/eu.js
  25. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/fa.js
  26. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/fi.js
  27. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/fo.js
  28. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/fr-ca.js
  29. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/fr.js
  30. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/gl.js
  31. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/gu.js
  32. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/he.js
  33. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/hi.js
  34. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/hr.js
  35. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/hu.js
  36. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/id.js
  37. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/is.js
  38. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/it.js
  39. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ja.js
  40. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ka.js
  41. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/km.js
  42. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ko.js
  43. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ku.js
  44. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/lt.js
  45. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/lv.js
  46. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/mk.js
  47. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/mn.js
  48. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ms.js
  49. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/nb.js
  50. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/nl.js
  51. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/no.js
  52. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/oc.js
  53. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/pl.js
  54. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/pt-br.js
  55. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/pt.js
  56. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ro.js
  57. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ru.js
  58. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/si.js
  59. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sk.js
  60. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sl.js
  61. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sq.js
  62. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sr-latn.js
  63. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sr.js
  64. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sv.js
  65. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/th.js
  66. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/tr.js
  67. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/tt.js
  68. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ug.js
  69. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/uk.js
  70. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/vi.js
  71. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/zh-cn.js
  72. 22 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/zh.js
  73. 1724 0
      main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/plugin.js

+ 573 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/dialogs/image2_chamilo.js

@@ -0,0 +1,573 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or http://ckeditor.com/license
+ */
+
+/**
+ * @fileOverview Image plugin based on Widgets API
+ */
+
+'use strict';
+
+CKEDITOR.dialog.add( 'image2_chamilo', function( editor ) {
+
+	// RegExp: 123, 123px, empty string ""
+	var regexGetSizeOrEmpty = /(^\s*(\d+)(px)?\s*$)|^$/i,
+
+		lockButtonId = CKEDITOR.tools.getNextId(),
+		resetButtonId = CKEDITOR.tools.getNextId(),
+
+		lang = editor.lang.image2_chamilo,
+		commonLang = editor.lang.common,
+
+		lockResetStyle = 'margin-top:18px;width:40px;height:20px;',
+		lockResetHtml = new CKEDITOR.template(
+			'<div>' +
+				'<a href="javascript:void(0)" tabindex="-1" title="' + lang.lockRatio + '" class="cke_btn_locked" id="{lockButtonId}" role="checkbox">' +
+					'<span class="cke_icon"></span>' +
+					'<span class="cke_label">' + lang.lockRatio + '</span>' +
+				'</a>' +
+
+				'<a href="javascript:void(0)" tabindex="-1" title="' + lang.resetSize + '" class="cke_btn_reset" id="{resetButtonId}" role="button">' +
+					'<span class="cke_label">' + lang.resetSize + '</span>' +
+				'</a>' +
+			'</div>' ).output( {
+				lockButtonId: lockButtonId,
+				resetButtonId: resetButtonId
+			} ),
+
+		helpers = CKEDITOR.plugins.image2_chamilo,
+
+		// Editor instance configuration.
+		config = editor.config,
+
+		hasFileBrowser = !!( config.filebrowserImageBrowseUrl || config.filebrowserBrowseUrl ),
+
+		// Content restrictions defined by the widget which
+		// impact on dialog structure and presence of fields.
+		features = editor.widgets.registered.image.features,
+
+		// Functions inherited from image2_chamilo plugin.
+		getNatural = helpers.getNatural,
+
+		// Global variables referring to the dialog's context.
+		doc, widget, image,
+
+		// Global variable referring to this dialog's image pre-loader.
+		preLoader,
+
+		// Global variables holding the original size of the image.
+		domWidth, domHeight,
+
+		// Global variables related to image pre-loading.
+		preLoadedWidth, preLoadedHeight, srcChanged,
+
+		// Global variables related to size locking.
+		lockRatio, userDefinedLock,
+
+		// Global variables referring to dialog fields and elements.
+		lockButton, resetButton, widthField, heightField,
+
+		natural;
+
+	// Validates dimension. Allowed values are:
+	// "123px", "123", "" (empty string)
+	function validateDimension() {
+		var match = this.getValue().match( regexGetSizeOrEmpty ),
+			isValid = !!( match && parseInt( match[ 1 ], 10 ) !== 0 );
+
+		if ( !isValid )
+			alert( commonLang[ 'invalid' + CKEDITOR.tools.capitalize( this.id ) ] ); // jshint ignore:line
+
+		return isValid;
+	}
+
+	// Creates a function that pre-loads images. The callback function passes
+	// [image, width, height] or null if loading failed.
+	//
+	// @returns {Function}
+	function createPreLoader() {
+		var image = doc.createElement( 'img' ),
+			listeners = [];
+
+		function addListener( event, callback ) {
+			listeners.push( image.once( event, function( evt ) {
+				removeListeners();
+				callback( evt );
+			} ) );
+		}
+
+		function removeListeners() {
+			var l;
+
+			while ( ( l = listeners.pop() ) )
+				l.removeListener();
+		}
+
+		// @param {String} src.
+		// @param {Function} callback.
+		return function( src, callback, scope ) {
+			addListener( 'load', function() {
+				// Don't use image.$.(width|height) since it's buggy in IE9-10 (#11159)
+				var dimensions = getNatural( image );
+
+				callback.call( scope, image, dimensions.width, dimensions.height );
+			} );
+
+			addListener( 'error', function() {
+				callback( null );
+			} );
+
+			addListener( 'abort', function() {
+				callback( null );
+			} );
+
+			image.setAttribute( 'src',
+				( config.baseHref || '' ) + src + '?' + Math.random().toString( 16 ).substring( 2 ) );
+		};
+	}
+
+	// This function updates width and height fields once the
+	// "src" field is altered. Along with dimensions, also the
+	// dimensions lock is adjusted.
+	function onChangeSrc() {
+		var value = this.getValue();
+
+		toggleDimensions( false );
+
+		// Remember that src is different than default.
+		if ( value !== widget.data.src ) {
+			// Update dimensions of the image once it's preloaded.
+			preLoader( value, function( image, width, height ) {
+				// Re-enable width and height fields.
+				toggleDimensions( true );
+
+				// There was problem loading the image. Unlock ratio.
+				if ( !image )
+					return toggleLockRatio( false );
+
+				// Fill width field with the width of the new image.
+				widthField.setValue( editor.config.image2_chamilo_prefillDimensions === false ? 0 : width );
+
+				// Fill height field with the height of the new image.
+				heightField.setValue( editor.config.image2_chamilo_prefillDimensions === false ? 0 : height );
+
+				// Cache the new width.
+				preLoadedWidth = width;
+
+				// Cache the new height.
+				preLoadedHeight = height;
+
+				// Check for new lock value if image exist.
+				toggleLockRatio( helpers.checkHasNaturalRatio( image ) );
+			} );
+
+			srcChanged = true;
+		}
+
+		// Value is the same as in widget data but is was
+		// modified back in time. Roll back dimensions when restoring
+		// default src.
+		else if ( srcChanged ) {
+			// Re-enable width and height fields.
+			toggleDimensions( true );
+
+			// Restore width field with cached width.
+			widthField.setValue( domWidth );
+
+			// Restore height field with cached height.
+			heightField.setValue( domHeight );
+
+			// Src equals default one back again.
+			srcChanged = false;
+		}
+
+		// Value is the same as in widget data and it hadn't
+		// been modified.
+		else {
+			// Re-enable width and height fields.
+			toggleDimensions( true );
+		}
+	}
+
+	function onChangeDimension() {
+		// If ratio is un-locked, then we don't care what's next.
+		if ( !lockRatio )
+			return;
+
+		var value = this.getValue();
+
+		// No reason to auto-scale or unlock if the field is empty.
+		if ( !value )
+			return;
+
+		// If the value of the field is invalid (e.g. with %), unlock ratio.
+		if ( !value.match( regexGetSizeOrEmpty ) )
+			toggleLockRatio( false );
+
+		// No automatic re-scale when dimension is '0'.
+		if ( value === '0' )
+			return;
+
+		var isWidth = this.id == 'width',
+			// If dialog opened for the new image, domWidth and domHeight
+			// will be empty. Use dimensions from pre-loader in such case instead.
+			width = domWidth || preLoadedWidth,
+			height = domHeight || preLoadedHeight;
+
+		// If changing width, then auto-scale height.
+		if ( isWidth )
+			value = Math.round( height * ( value / width ) );
+
+		// If changing height, then auto-scale width.
+		else
+			value = Math.round( width * ( value / height ) );
+
+		// If the value is a number, apply it to the other field.
+		if ( !isNaN( value ) )
+			( isWidth ? heightField : widthField ).setValue( value );
+	}
+
+	// Set-up function for lock and reset buttons:
+	// 	* Adds lock and reset buttons to focusables. Check if button exist first
+	// 	  because it may be disabled e.g. due to ACF restrictions.
+	// 	* Register mouseover and mouseout event listeners for UI manipulations.
+	// 	* Register click event listeners for buttons.
+	function onLoadLockReset() {
+		var dialog = this.getDialog();
+
+		function setupMouseClasses( el ) {
+			el.on( 'mouseover', function() {
+				this.addClass( 'cke_btn_over' );
+			}, el );
+
+			el.on( 'mouseout', function() {
+				this.removeClass( 'cke_btn_over' );
+			}, el );
+		}
+
+		// Create references to lock and reset buttons for this dialog instance.
+		lockButton = doc.getById( lockButtonId );
+		resetButton = doc.getById( resetButtonId );
+
+		// Activate (Un)LockRatio button
+		if ( lockButton ) {
+			// Consider that there's an additional focusable field
+			// in the dialog when the "browse" button is visible.
+			dialog.addFocusable( lockButton, 4 + hasFileBrowser );
+
+			lockButton.on( 'click', function( evt ) {
+				toggleLockRatio();
+				evt.data && evt.data.preventDefault();
+			}, this.getDialog() );
+
+			setupMouseClasses( lockButton );
+		}
+
+		// Activate the reset size button.
+		if ( resetButton ) {
+			// Consider that there's an additional focusable field
+			// in the dialog when the "browse" button is visible.
+			dialog.addFocusable( resetButton, 5 + hasFileBrowser );
+
+			// Fills width and height fields with the original dimensions of the
+			// image (stored in widget#data since widget#init).
+			resetButton.on( 'click', function( evt ) {
+				// If there's a new image loaded, reset button should revert
+				// cached dimensions of pre-loaded DOM element.
+				if ( srcChanged ) {
+					widthField.setValue( preLoadedWidth );
+					heightField.setValue( preLoadedHeight );
+				}
+
+				// If the old image remains, reset button should revert
+				// dimensions as loaded when the dialog was first shown.
+				else {
+					widthField.setValue( domWidth );
+					heightField.setValue( domHeight );
+				}
+
+				evt.data && evt.data.preventDefault();
+			}, this );
+
+			setupMouseClasses( resetButton );
+		}
+	}
+
+	function toggleLockRatio( enable ) {
+		// No locking if there's no radio (i.e. due to ACF).
+		if ( !lockButton )
+			return;
+
+		if ( typeof enable == 'boolean' ) {
+			// If user explicitly wants to decide whether
+			// to lock or not, don't do anything.
+			if ( userDefinedLock )
+				return;
+
+			lockRatio = enable;
+		}
+
+		// Undefined. User changed lock value.
+		else {
+			var width = widthField.getValue(),
+				height;
+
+			userDefinedLock = true;
+			lockRatio = !lockRatio;
+
+			// Automatically adjust height to width to match
+			// the original ratio (based on dom- dimensions).
+			if ( lockRatio && width ) {
+				height = domHeight / domWidth * width;
+
+				if ( !isNaN( height ) )
+					heightField.setValue( Math.round( height ) );
+			}
+		}
+
+		lockButton[ lockRatio ? 'removeClass' : 'addClass' ]( 'cke_btn_unlocked' );
+		lockButton.setAttribute( 'aria-checked', lockRatio );
+
+		// Ratio button hc presentation - WHITE SQUARE / BLACK SQUARE
+		if ( CKEDITOR.env.hc ) {
+			var icon = lockButton.getChild( 0 );
+			icon.setHtml( lockRatio ? CKEDITOR.env.ie ? '\u25A0' : '\u25A3' : CKEDITOR.env.ie ? '\u25A1' : '\u25A2' );
+		}
+	}
+
+	function toggleDimensions( enable ) {
+		var method = enable ? 'enable' : 'disable';
+
+		widthField[ method ]();
+		heightField[ method ]();
+	}
+
+	var srcBoxChildren = [
+			{
+				id: 'src',
+				type: 'text',
+				label: commonLang.url,
+				onKeyup: onChangeSrc,
+				onChange: onChangeSrc,
+				setup: function( widget ) {
+					this.setValue( widget.data.src );
+				},
+				commit: function( widget ) {
+					widget.setData( 'src', this.getValue() );
+				},
+				validate: CKEDITOR.dialog.validate.notEmpty( lang.urlMissing )
+			}
+		];
+
+	// Render the "Browse" button on demand to avoid an "empty" (hidden child)
+	// space in dialog layout that distorts the UI.
+	if ( hasFileBrowser ) {
+		srcBoxChildren.push( {
+			type: 'button',
+			id: 'browse',
+			// v-align with the 'txtUrl' field.
+			// TODO: We need something better than a fixed size here.
+			style: 'display:inline-block;margin-top:14px;',
+			align: 'center',
+			label: editor.lang.common.browseServer,
+			hidden: true,
+			filebrowser: 'info:src'
+		} );
+	}
+
+	return {
+		title: lang.title,
+		minWidth: 250,
+		minHeight: 100,
+		onLoad: function() {
+			// Create a "global" reference to the document for this dialog instance.
+			doc = this._.element.getDocument();
+
+			// Create a pre-loader used for determining dimensions of new images.
+			preLoader = createPreLoader();
+		},
+		onShow: function() {
+			// Create a "global" reference to edited widget.
+			widget = this.widget;
+
+			// Create a "global" reference to widget's image.
+			image = widget.parts.image;
+
+			// Reset global variables.
+			srcChanged = userDefinedLock = lockRatio = false;
+
+			// Natural dimensions of the image.
+			natural = getNatural( image );
+
+			// Get the natural width of the image.
+			preLoadedWidth = domWidth = natural.width;
+
+			// Get the natural height of the image.
+			preLoadedHeight = domHeight = natural.height;
+		},
+		contents: [
+			{
+				id: 'info',
+				label: lang.infoTab,
+				elements: [
+					{
+						type: 'vbox',
+						padding: 0,
+						children: [
+							{
+								type: 'hbox',
+								widths: [ '100%' ],
+								className: 'cke_dialog_image_url',
+								children: srcBoxChildren
+							}
+						]
+					},
+					{
+						id: 'alt',
+						type: 'text',
+						label: lang.alt,
+						setup: function( widget ) {
+							this.setValue( widget.data.alt );
+						},
+						commit: function( widget ) {
+							widget.setData( 'alt', this.getValue() );
+						},
+						validate: editor.config.image2_chamilo_altRequired === true ? CKEDITOR.dialog.validate.notEmpty( lang.altMissing ) : null
+					},
+					{
+						type: 'hbox',
+						widths: [ '25%', '25%', '50%' ],
+						requiredContent: features.dimension.requiredContent,
+						children: [
+							{
+								type: 'text',
+								width: '45px',
+								id: 'width',
+								label: commonLang.width,
+								validate: validateDimension,
+								onKeyUp: onChangeDimension,
+								onLoad: function() {
+									widthField = this;
+								},
+								setup: function( widget ) {
+									this.setValue( widget.data.width );
+								},
+								commit: function( widget ) {
+									widget.setData( 'width', this.getValue() );
+								}
+							},
+							{
+								type: 'text',
+								id: 'height',
+								width: '45px',
+								label: commonLang.height,
+								validate: validateDimension,
+								onKeyUp: onChangeDimension,
+								onLoad: function() {
+									heightField = this;
+								},
+								setup: function( widget ) {
+									this.setValue( widget.data.height );
+								},
+								commit: function( widget ) {
+									widget.setData( 'height', this.getValue() );
+								}
+							},
+							{
+								id: 'lock',
+								type: 'html',
+								style: lockResetStyle,
+								onLoad: onLoadLockReset,
+								setup: function( widget ) {
+									toggleLockRatio( widget.data.lock );
+								},
+								commit: function( widget ) {
+									widget.setData( 'lock', lockRatio );
+								},
+								html: lockResetHtml
+							}
+						]
+					},
+					{
+						type: 'hbox',
+						id: 'alignment',
+						requiredContent: features.align.requiredContent,
+						children: [
+							{
+								id: 'align',
+								type: 'radio',
+								items: [
+									[ commonLang.alignNone, 'none' ],
+									[ commonLang.alignLeft, 'left' ],
+									[ commonLang.alignCenter, 'center' ],
+									[ commonLang.alignRight, 'right' ]
+								],
+								label: commonLang.align,
+								setup: function( widget ) {
+									this.setValue( widget.data.align );
+								},
+								commit: function( widget ) {
+									widget.setData( 'align', this.getValue() );
+								}
+							}
+						]
+					},
+					{
+						id: 'hasCaption',
+						type: 'checkbox',
+						label: lang.captioned,
+						requiredContent: features.caption.requiredContent,
+						setup: function( widget ) {
+							this.setValue( widget.data.hasCaption );
+						},
+						commit: function( widget ) {
+							widget.setData( 'hasCaption', this.getValue() );
+						}
+					},
+					{
+						id: 'isResponsive',
+						type: 'checkbox',
+						label: lang.responsive,
+						requiredContent: features.responsive.requiredContent,
+						setup: function ( widget ) {
+							this.setValue( widget.data.isResponsive );
+                        },
+						commit: function ( widget ) {
+							var img = widget;
+
+							if (widget.element.$.tagName === 'FIGURE') {
+
+								img = widget.element.$.firstChild;
+							}
+
+                            img.className += ' img-responsive ';
+							widget.setData( 'isResponsive', this.getValue() );
+                        }
+					}
+				]
+			},
+			{
+				id: 'Upload',
+				hidden: true,
+				filebrowser: 'uploadButton',
+				label: lang.uploadTab,
+				elements: [
+					{
+						type: 'file',
+						id: 'upload',
+						label: lang.btnUpload,
+						style: 'height:40px'
+					},
+					{
+						type: 'fileButton',
+						id: 'uploadButton',
+						filebrowser: 'info:src',
+						label: lang.btnUpload,
+						'for': [ 'Upload', 'upload' ]
+					}
+				]
+			}
+		]
+	};
+} );

BIN
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/icons/hidpi/image.png


BIN
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/icons/image.png


+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/af.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'af', {
+	alt: 'Alternatiewe teks',
+	btnUpload: 'Stuur na bediener',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Afbeelding informasie',
+	lockRatio: 'Vaste proporsie',
+	menu: 'Afbeelding eienskappe',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Herstel grootte',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Afbeelding eienskappe',
+	uploadTab: 'Oplaai',
+	urlMissing: 'Die URL na die afbeelding ontbreek.',
+	altMissing: 'Alternative text is missing.', // MISSING
+	responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ar.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'ar', {
+	alt: 'عنوان الصورة',
+	btnUpload: 'أرسلها للخادم',
+	captioned: 'صورة ذات اسم',
+	captionPlaceholder: 'تسمية',
+	infoTab: 'معلومات الصورة',
+	lockRatio: 'تناسق الحجم',
+	menu: 'خصائص الصورة',
+	pathName: 'صورة',
+	pathNameCaption: 'تسمية',
+	resetSize: 'إستعادة الحجم الأصلي',
+	resizer: 'انقر ثم اسحب للتحجيم',
+	title: 'خصائص الصورة',
+	uploadTab: 'رفع',
+	urlMissing: 'عنوان مصدر الصورة مفقود',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/az.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'az', {
+	alt: 'Alternativ mətn',
+	btnUpload: 'Serverə göndər',
+	captioned: 'Altyazı olan şəkil',
+	captionPlaceholder: 'Altyazı',
+	infoTab: 'Şəkil haqqında məlumat',
+	lockRatio: 'Ölçülərin nisbəti saxla',
+	menu: 'Şəklin seçimləri',
+	pathName: 'Şəkil',
+	pathNameCaption: 'Altyazı',
+	resetSize: 'Ölçüləri qaytar',
+	resizer: 'Ölçülər dəyişmək üçün tıklayın və aparın',
+	title: 'Şəklin seçimləri',
+	uploadTab: 'Serverə yüklə',
+	urlMissing: 'Şəklin ünvanı yanlışdır.',
+	altMissing: 'Alternativ mətn tapılmayıb',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/bg.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'bg', {
+	alt: 'Алтернативен текст',
+	btnUpload: 'Изпрати я на сървъра',
+	captioned: 'Надписано изображение',
+	captionPlaceholder: 'Надпис',
+	infoTab: 'Детайли за изображението',
+	lockRatio: 'Заключване на съотношението',
+	menu: 'Настройки на изображението',
+	pathName: 'изображение',
+	pathNameCaption: 'надпис',
+	resetSize: 'Нулиране на размер',
+	resizer: 'Кликни и влачи, за да преоразмериш',
+	title: 'Настройки на изображението',
+	uploadTab: 'Качване',
+	urlMissing: 'URL адреса на изображението липсва.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/bn.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'bn', {
+	alt: 'বিকল্প টেক্সট',
+	btnUpload: 'ইহাকে সার্ভারে প্রেরন কর',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'ছবির তথ্য',
+	lockRatio: 'অনুপাত লক কর',
+	menu: 'ছবির প্রোপার্টি',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'সাইজ পূর্বাবস্থায় ফিরিয়ে দাও',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'ছবির প্রোপার্টি',
+	uploadTab: 'আপলোড',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/bs.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'bs', {
+	alt: 'Tekst na slici',
+	btnUpload: 'Šalji na server',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Info slike',
+	lockRatio: 'Zakljuèaj odnos',
+	menu: 'Svojstva slike',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Resetuj dimenzije',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Svojstva slike',
+	uploadTab: 'Šalji',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ca.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'ca', {
+	alt: 'Text alternatiu',
+	btnUpload: 'Envia-la al servidor',
+	captioned: 'Imatge amb subtítol',
+	captionPlaceholder: 'Títol',
+	infoTab: 'Informació de la imatge',
+	lockRatio: 'Bloqueja les proporcions',
+	menu: 'Propietats de la imatge',
+	pathName: 'imatge',
+	pathNameCaption: 'subtítol',
+	resetSize: 'Restaura la mida',
+	resizer: 'Clicar i arrossegar per redimensionar',
+	title: 'Propietats de la imatge',
+	uploadTab: 'Puja',
+	urlMissing: 'Falta la URL de la imatge.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/cs.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'cs', {
+	alt: 'Alternativní text',
+	btnUpload: 'Odeslat na server',
+	captioned: 'Obrázek s popisem',
+	captionPlaceholder: 'Popis',
+	infoTab: 'Informace o obrázku',
+	lockRatio: 'Zámek',
+	menu: 'Vlastnosti obrázku',
+	pathName: 'Obrázek',
+	pathNameCaption: 'Popis',
+	resetSize: 'Původní velikost',
+	resizer: 'Klepněte a táhněte pro změnu velikosti',
+	title: 'Vlastnosti obrázku',
+	uploadTab: 'Odeslat',
+	urlMissing: 'Zadané URL zdroje obrázku nebylo nalezeno.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/cy.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'cy', {
+	alt: 'Testun Amgen',
+	btnUpload: 'Anfon i\'r Gweinydd',
+	captioned: 'Delwedd â phennawd',
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Gwyb Delwedd',
+	lockRatio: 'Cloi Cymhareb',
+	menu: 'Priodweddau Delwedd',
+	pathName: 'delwedd',
+	pathNameCaption: 'pennawd',
+	resetSize: 'Ailosod Maint',
+	resizer: 'Clicio a llusgo i ail-meintio',
+	title: 'Priodweddau Delwedd',
+	uploadTab: 'Lanlwytho',
+	urlMissing: 'URL gwreiddiol y ddelwedd ar goll.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/da.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'da', {
+	alt: 'Alternativ tekst',
+	btnUpload: 'Upload fil til serveren',
+	captioned: 'Tekstet billede',
+	captionPlaceholder: 'Tekst',
+	infoTab: 'Generelt',
+	lockRatio: 'Lås størrelsesforhold',
+	menu: 'Egenskaber for billede',
+	pathName: 'billede',
+	pathNameCaption: 'tekst',
+	resetSize: 'Nulstil størrelse',
+	resizer: 'Klik og træk for at ændre størrelsen',
+	title: 'Egenskaber for billede',
+	uploadTab: 'Upload',
+	urlMissing: 'Kilde på billed-URL mangler',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/de-ch.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'de-ch', {
+	alt: 'Alternativer Text',
+	btnUpload: 'Zum Server senden',
+	captioned: 'Bild mit Überschrift',
+	captionPlaceholder: 'Überschrift',
+	infoTab: 'Bildinfo',
+	lockRatio: 'Größenverhältnis beibehalten',
+	menu: 'Bildeigenschaften',
+	pathName: 'Bild',
+	pathNameCaption: 'Überschrift',
+	resetSize: 'Grösse zurücksetzen',
+	resizer: 'Zum Vergrössern auswählen und ziehen',
+	title: 'Bild-Eigenschaften',
+	uploadTab: 'Hochladen',
+	urlMissing: 'Bildquellen-URL fehlt.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/de.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'de', {
+	alt: 'Alternativer Text',
+	btnUpload: 'Zum Server senden',
+	captioned: 'Bild mit Überschrift',
+	captionPlaceholder: 'Überschrift',
+	infoTab: 'Bildinfo',
+	lockRatio: 'Größenverhältnis beibehalten',
+	menu: 'Bildeigenschaften',
+	pathName: 'Bild',
+	pathNameCaption: 'Überschrift',
+	resetSize: 'Größe zurücksetzen',
+	resizer: 'Zum Vergrößern auswählen und ziehen',
+	title: 'Bild-Eigenschaften',
+	uploadTab: 'Hochladen',
+	urlMissing: 'Bildquellen-URL fehlt.',
+	altMissing: 'Alternativer Text fehlt.',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/el.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'el', {
+	alt: 'Εναλλακτικό Κείμενο',
+	btnUpload: 'Αποστολή στον Διακομιστή',
+	captioned: 'Εικόνα με λεζάντα',
+	captionPlaceholder: 'Λεζάντα',
+	infoTab: 'Πληροφορίες Εικόνας',
+	lockRatio: 'Κλείδωμα Αναλογίας',
+	menu: 'Ιδιότητες Εικόνας',
+	pathName: 'εικόνα',
+	pathNameCaption: 'λεζάντα',
+	resetSize: 'Επαναφορά Αρχικού Μεγέθους',
+	resizer: 'Κάνετε κλικ και σύρετε το ποντίκι για να αλλάξετε το μέγεθος',
+	title: 'Ιδιότητες Εικόνας',
+	uploadTab: 'Αποστολή',
+	urlMissing: 'Λείπει το πηγαίο URL της εικόνας.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/en-au.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'en-au', {
+	alt: 'Alternative Text',
+	btnUpload: 'Send it to the Server',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Image Info',
+	lockRatio: 'Lock Ratio',
+	menu: 'Image Properties',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Reset Size',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Image Properties',
+	uploadTab: 'Upload',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/en-ca.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'en-ca', {
+	alt: 'Alternative Text',
+	btnUpload: 'Send it to the Server',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Image Info',
+	lockRatio: 'Lock Ratio',
+	menu: 'Image Properties',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Reset Size',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Image Properties',
+	uploadTab: 'Upload',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/en-gb.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'en-gb', {
+	alt: 'Alternative Text',
+	btnUpload: 'Send it to the Server',
+	captioned: 'Captioned image',
+	captionPlaceholder: 'Caption',
+	infoTab: 'Image Info',
+	lockRatio: 'Lock Ratio',
+	menu: 'Image Properties',
+	pathName: 'image',
+	pathNameCaption: 'caption',
+	resetSize: 'Reset Size',
+	resizer: 'Click and drag to resize',
+	title: 'Image Properties',
+	uploadTab: 'Upload',
+	urlMissing: 'Image source URL is missing.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/en.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'en', {
+	alt: 'Alternative Text',
+	btnUpload: 'Send it to the Server',
+	captioned: 'Captioned image',
+	captionPlaceholder: 'Caption',
+	infoTab: 'Image Info',
+	lockRatio: 'Lock Ratio',
+	menu: 'Image Properties',
+	pathName: 'image',
+	pathNameCaption: 'caption',
+	resetSize: 'Reset Size',
+	resizer: 'Click and drag to resize',
+	title: 'Image Properties',
+	uploadTab: 'Upload',
+	urlMissing: 'Image source URL is missing.',
+	altMissing: 'Alternative text is missing.',
+    responsive: 'Responsive image'
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/eo.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'eo', {
+	alt: 'Anstataŭiga Teksto',
+	btnUpload: 'Sendu al Servilo',
+	captioned: 'Bildo kun apudskribo',
+	captionPlaceholder: 'Apudskribo',
+	infoTab: 'Informoj pri Bildo',
+	lockRatio: 'Konservi Proporcion',
+	menu: 'Atributoj de Bildo',
+	pathName: 'bildo',
+	pathNameCaption: 'apudskribo',
+	resetSize: 'Origina Grando',
+	resizer: 'Kliki kaj treni por ŝanĝi la grandon',
+	title: 'Atributoj de Bildo',
+	uploadTab: 'Alŝuti',
+	urlMissing: 'La fontretadreso de la bildo mankas.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/es.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'es', {
+	alt: 'Texto Alternativo',
+	btnUpload: 'Enviar al Servidor',
+	captioned: 'Imagen subtitulada',
+	captionPlaceholder: 'Leyenda',
+	infoTab: 'Información de Imagen',
+	lockRatio: 'Proporcional',
+	menu: 'Propiedades de Imagen',
+	pathName: 'image',
+	pathNameCaption: 'subtítulo',
+	resetSize: 'Tamaño Original',
+	resizer: 'Dar clic y arrastrar para cambiar tamaño',
+	title: 'Propiedades de Imagen',
+	uploadTab: 'Cargar',
+	urlMissing: 'Debe indicar la URL de la imagen.',
+	altMissing: 'Falta el texto alternativo.',
+    responsive: 'Imagen responsiva'
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/et.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'et', {
+	alt: 'Alternatiivne tekst',
+	btnUpload: 'Saada serverisse',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Pildi info',
+	lockRatio: 'Lukusta kuvasuhe',
+	menu: 'Pildi omadused',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Lähtesta suurus',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Pildi omadused',
+	uploadTab: 'Lae üles',
+	urlMissing: 'Pildi lähte-URL on puudu.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/eu.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'eu', {
+	alt: 'Ordezko testua',
+	btnUpload: 'Bidali zerbitzarira',
+	captioned: 'Argazki oina',
+	captionPlaceholder: 'Argazki oina',
+	infoTab: 'Irudiaren informazioa',
+	lockRatio: 'Blokeatu erlazioa',
+	menu: 'Irudiaren propietateak',
+	pathName: 'Irudia',
+	pathNameCaption: 'Argazki oina',
+	resetSize: 'Berrezarri tamaina',
+	resizer: 'Klikatu eta arrastatu tamainaz aldatzeko',
+	title: 'Irudiaren propietateak',
+	uploadTab: 'Kargatu',
+	urlMissing: 'Irudiaren iturburuaren URLa falta da.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/fa.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'fa', {
+	alt: 'متن جایگزین',
+	btnUpload: 'به سرور بفرست',
+	captioned: 'تصویر زیرنویس شده',
+	captionPlaceholder: 'عنوان',
+	infoTab: 'اطلاعات تصویر',
+	lockRatio: 'قفل کردن نسبت',
+	menu: 'ویژگی​های تصویر',
+	pathName: 'تصویر',
+	pathNameCaption: 'عنوان',
+	resetSize: 'بازنشانی اندازه',
+	resizer: 'کلیک و کشیدن برای تغییر اندازه',
+	title: 'ویژگی​های تصویر',
+	uploadTab: 'بالاگذاری',
+	urlMissing: 'آدرس URL اصلی تصویر یافت نشد.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/fi.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'fi', {
+	alt: 'Vaihtoehtoinen teksti',
+	btnUpload: 'Lähetä palvelimelle',
+	captioned: 'Kuva kuvatekstillä',
+	captionPlaceholder: 'Kuvateksti',
+	infoTab: 'Kuvan tiedot',
+	lockRatio: 'Lukitse suhteet',
+	menu: 'Kuvan ominaisuudet',
+	pathName: 'kuva',
+	pathNameCaption: 'kuvateksti',
+	resetSize: 'Alkuperäinen koko',
+	resizer: 'Klikkaa ja raahaa muuttaaksesi kokoa',
+	title: 'Kuvan ominaisuudet',
+	uploadTab: 'Lisää tiedosto',
+	urlMissing: 'Kuvan lähdeosoite puuttuu.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/fo.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'fo', {
+	alt: 'Alternativur tekstur',
+	btnUpload: 'Send til ambætaran',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Myndaupplýsingar',
+	lockRatio: 'Læs lutfallið',
+	menu: 'Myndaeginleikar',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Upprunastødd',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Myndaeginleikar',
+	uploadTab: 'Send til ambætaran',
+	urlMissing: 'URL til mynd manglar.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/fr-ca.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'fr-ca', {
+	alt: 'Texte alternatif',
+	btnUpload: 'Envoyer sur le serveur',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Informations sur l\'image2',
+	lockRatio: 'Verrouiller les proportions',
+	menu: 'Propriétés de l\'image2',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Taille originale',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Propriétés de l\'image2',
+	uploadTab: 'Téléverser',
+	urlMissing: 'L\'URL de la source de l\'image est manquant.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/fr.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2-chamilo', 'fr', {
+	alt: 'Texte alternatif',
+	btnUpload: 'Envoyer sur le serveur',
+	captioned: 'Image légendée',
+	captionPlaceholder: 'Légende',
+	infoTab: 'Informations sur l\'image',
+	lockRatio: 'Conserver les proportions',
+	menu: 'Propriétés de l\'image',
+	pathName: 'image',
+	pathNameCaption: 'légende',
+	resetSize: 'Réinitialiser la taille',
+	resizer: 'Cliquer et glisser pour redimensionner',
+	title: 'Propriétés de l\'image',
+	uploadTab: 'Téléverser',
+	urlMissing: 'L\'URL source de l\'image est manquante.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/gl.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'gl', {
+	alt: 'Texto alternativo',
+	btnUpload: 'Enviar ao servidor',
+	captioned: 'Imaxe con lenda',
+	captionPlaceholder: 'Lenda',
+	infoTab: 'Información da imaxe',
+	lockRatio: 'Proporcional',
+	menu: 'Propiedades da imaxe',
+	pathName: 'Imaxe',
+	pathNameCaption: 'lenda',
+	resetSize: 'Tamaño orixinal',
+	resizer: 'Prema e arrastre para axustar o tamaño',
+	title: 'Propiedades da imaxe',
+	uploadTab: 'Cargar',
+	urlMissing: 'Non se atopa o URL da imaxe.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/gu.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'gu', {
+	alt: 'ઑલ્ટર્નટ ટેક્સ્ટ',
+	btnUpload: 'આ સર્વરને મોકલવું',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'ચિત્ર ની જાણકારી',
+	lockRatio: 'લૉક ગુણોત્તર',
+	menu: 'ચિત્રના ગુણ',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'રીસેટ સાઇઝ',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'ચિત્રના ગુણ',
+	uploadTab: 'અપલોડ',
+	urlMissing: 'ઈમેજની મૂળ URL છે નહી.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/he.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'he', {
+	alt: 'טקסט חלופי',
+	btnUpload: 'שליחה לשרת',
+	captioned: 'כותרת תמונה',
+	captionPlaceholder: 'כותרת',
+	infoTab: 'מידע על התמונה',
+	lockRatio: 'נעילת היחס',
+	menu: 'תכונות התמונה',
+	pathName: 'תמונה',
+	pathNameCaption: 'כותרת',
+	resetSize: 'איפוס הגודל',
+	resizer: 'לחץ וגרור לשינוי הגודל',
+	title: 'מאפייני התמונה',
+	uploadTab: 'העלאה',
+	urlMissing: 'כתובת התמונה חסרה.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/hi.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'hi', {
+	alt: 'वैकल्पिक टेक्स्ट',
+	btnUpload: 'इसे सर्वर को भेजें',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'तस्वीर की जानकारी',
+	lockRatio: 'लॉक अनुपात',
+	menu: 'तस्वीर प्रॉपर्टीज़',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'रीसॅट साइज़',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'तस्वीर प्रॉपर्टीज़',
+	uploadTab: 'अपलोड',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/hr.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'hr', {
+	alt: 'Alternativni tekst',
+	btnUpload: 'Pošalji na server',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Info slike',
+	lockRatio: 'Zaključaj odnos',
+	menu: 'Svojstva slika',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Obriši veličinu',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Svojstva slika',
+	uploadTab: 'Pošalji',
+	urlMissing: 'Nedostaje URL slike.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/hu.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'hu', {
+	alt: 'Buborék szöveg',
+	btnUpload: 'Küldés a szerverre',
+	captioned: 'Feliratozott kép',
+	captionPlaceholder: 'Képfelirat',
+	infoTab: 'Alaptulajdonságok',
+	lockRatio: 'Arány megtartása',
+	menu: 'Kép tulajdonságai',
+	pathName: 'kép',
+	pathNameCaption: 'felirat',
+	resetSize: 'Eredeti méret',
+	resizer: 'Kattints és húzz az átméretezéshez',
+	title: 'Kép tulajdonságai',
+	uploadTab: 'Feltöltés',
+	urlMissing: 'Hiányzik a kép URL-je',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/id.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'id', {
+	alt: 'Teks alternatif',
+	btnUpload: 'Kirim ke Server',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Info Gambar',
+	lockRatio: 'Lock Ratio', // MISSING
+	menu: 'Image Properties', // MISSING
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Atur Ulang Ukuran',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Image Properties', // MISSING
+	uploadTab: 'Unggah',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/is.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'is', {
+	alt: 'Baklægur texti',
+	btnUpload: 'Hlaða upp',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Almennt',
+	lockRatio: 'Festa stærðarhlutfall',
+	menu: 'Eigindi myndar',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Reikna stærð',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Eigindi myndar',
+	uploadTab: 'Senda upp',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/it.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'it', {
+	alt: 'Testo alternativo',
+	btnUpload: 'Invia al server',
+	captioned: 'Immagine con didascalia',
+	captionPlaceholder: 'Didascalia',
+	infoTab: 'Informazioni immagine',
+	lockRatio: 'Blocca rapporto',
+	menu: 'Proprietà immagine',
+	pathName: 'immagine',
+	pathNameCaption: 'didascalia',
+	resetSize: 'Reimposta dimensione',
+	resizer: 'Fare clic e trascinare per ridimensionare',
+	title: 'Proprietà immagine',
+	uploadTab: 'Carica',
+	urlMissing: 'Manca l\'URL dell\'immagine.',
+	altMissing: 'Testo alternativo mancante.',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ja.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'ja', {
+	alt: '代替テキスト',
+	btnUpload: 'サーバーに送信',
+	captioned: 'キャプションを付ける',
+	captionPlaceholder: 'キャプション',
+	infoTab: '画像情報',
+	lockRatio: '比率を固定',
+	menu: '画像のプロパティ',
+	pathName: 'image',
+	pathNameCaption: 'caption',
+	resetSize: 'サイズをリセット',
+	resizer: 'ドラッグしてリサイズ',
+	title: '画像のプロパティ',
+	uploadTab: 'アップロード',
+	urlMissing: '画像のURLを入力してください。',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ka.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'ka', {
+	alt: 'სანაცვლო ტექსტი',
+	btnUpload: 'სერვერისთვის გაგზავნა',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'სურათის ინფორმცია',
+	lockRatio: 'პროპორციის შენარჩუნება',
+	menu: 'სურათის პარამეტრები',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'ზომის დაბრუნება',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'სურათის პარამეტრები',
+	uploadTab: 'აქაჩვა',
+	urlMissing: 'სურათის URL არაა შევსებული.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/km.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'km', {
+	alt: 'អត្ថបទជំនួស',
+	btnUpload: 'បញ្ជូនទៅកាន់ម៉ាស៊ីនផ្តល់សេវា',
+	captioned: 'រូប​ដែល​មាន​ចំណង​ជើង',
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'ពត៌មានអំពីរូបភាព',
+	lockRatio: 'ចាក់​សោ​ផល​ធៀប',
+	menu: 'លក្ខណៈ​សម្បត្តិ​រូប​ភាព',
+	pathName: 'រូបភាព',
+	pathNameCaption: 'ចំណងជើង',
+	resetSize: 'កំណត់ទំហំឡើងវិញ',
+	resizer: 'ចុច​ហើយ​ទាញ​ដើម្បី​ប្ដូរ​ទំហំ',
+	title: 'លក្ខណៈ​សម្បត្តិ​រូប​ភាប',
+	uploadTab: 'ផ្ទុក​ឡើង',
+	urlMissing: 'ខ្វះ URL ប្រភព​រូប​ភាព។',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ko.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'ko', {
+	alt: '대체 문자열',
+	btnUpload: '서버로 전송',
+	captioned: '이미지 설명 넣기',
+	captionPlaceholder: '설명',
+	infoTab: '이미지 정보',
+	lockRatio: '비율 유지',
+	menu: '이미지 속성',
+	pathName: '이미지',
+	pathNameCaption: '설명',
+	resetSize: '원래 크기로',
+	resizer: '크기를 조절하려면 클릭 후 드래그 하세요',
+	title: '이미지 속성',
+	uploadTab: '업로드',
+	urlMissing: '이미지 원본 주소(URL)가 없습니다.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ku.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'ku', {
+	alt: 'جێگرەوەی دەق',
+	btnUpload: 'ناردنی بۆ ڕاژه',
+	captioned: 'وێنەی بەسەردێر',
+	captionPlaceholder: 'سەردێر',
+	infoTab: 'زانیاری وێنه',
+	lockRatio: 'داخستنی ڕێژه',
+	menu: 'خاسیەتی وێنه',
+	pathName: 'وێنە',
+	pathNameCaption: 'سەردێر',
+	resetSize: 'ڕێکخستنەوەی قەباره',
+	resizer: 'کرتەبکە و ڕایبکێشە بۆ قەبارە گۆڕین',
+	title: 'خاسیەتی وێنه',
+	uploadTab: 'بارکردن',
+	urlMissing: 'سەرچاوەی بەستەری وێنه بزره',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/lt.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'lt', {
+	alt: 'Alternatyvus Tekstas',
+	btnUpload: 'Siųsti į serverį',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Vaizdo informacija',
+	lockRatio: 'Išlaikyti proporciją',
+	menu: 'Vaizdo savybės',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Atstatyti dydį',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Vaizdo savybės',
+	uploadTab: 'Siųsti',
+	urlMissing: 'Paveiksliuko nuorodos nėra.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/lv.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'lv', {
+	alt: 'Alternatīvais teksts',
+	btnUpload: 'Nosūtīt serverim',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Informācija par attēlu',
+	lockRatio: 'Nemainīga Augstuma/Platuma attiecība',
+	menu: 'Attēla īpašības',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Atjaunot sākotnējo izmēru',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Attēla īpašības',
+	uploadTab: 'Augšupielādēt',
+	urlMissing: 'Trūkst attēla atrašanās adrese.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/mk.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'mk', {
+	alt: 'Алтернативен текст',
+	btnUpload: 'Прикачи на сервер',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Информации за сликата',
+	lockRatio: 'Зачувај пропорција',
+	menu: 'Својства на сликата',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Ресетирај големина',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Својства на сликата',
+	uploadTab: 'Прикачи',
+	urlMissing: 'Недостасува URL-то на сликата.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/mn.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'mn', {
+	alt: 'Зургийг орлох бичвэр',
+	btnUpload: 'Үүнийг сервэррүү илгээ',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Зурагны мэдээлэл',
+	lockRatio: 'Радио түгжих',
+	menu: 'Зураг',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'хэмжээ дахин оноох',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Зураг',
+	uploadTab: 'Илгээж ачаалах',
+	urlMissing: 'Зургийн эх сурвалжийн хаяг (URL) байхгүй байна.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ms.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'ms', {
+	alt: 'Text Alternatif',
+	btnUpload: 'Hantar ke Server',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Info Imej',
+	lockRatio: 'Tetapkan Nisbah',
+	menu: 'Ciri-ciri Imej',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Saiz Set Semula',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Ciri-ciri Imej',
+	uploadTab: 'Muat Naik',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/nb.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'nb', {
+	alt: 'Alternativ tekst',
+	btnUpload: 'Send det til serveren',
+	captioned: 'Bilde med bildetekst',
+	captionPlaceholder: 'Bildetekst',
+	infoTab: 'Bildeinformasjon',
+	lockRatio: 'Lås forhold',
+	menu: 'Bildeegenskaper',
+	pathName: 'bilde',
+	pathNameCaption: 'bildetekst',
+	resetSize: 'Tilbakestill størrelse',
+	resizer: 'Klikk og dra for å endre størrelse',
+	title: 'Bildeegenskaper',
+	uploadTab: 'Last opp',
+	urlMissing: 'Bildets adresse mangler.',
+	altMissing: 'Alternativ tekst mangler.',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/nl.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'nl', {
+	alt: 'Alternatieve tekst',
+	btnUpload: 'Naar server verzenden',
+	captioned: 'Afbeelding met onderschrift',
+	captionPlaceholder: 'Onderschrift',
+	infoTab: 'Afbeeldingsinformatie',
+	lockRatio: 'Verhouding vergrendelen',
+	menu: 'Eigenschappen afbeelding',
+	pathName: 'afbeelding',
+	pathNameCaption: 'onderschrift',
+	resetSize: 'Afmetingen herstellen',
+	resizer: 'Klik en sleep om te herschalen',
+	title: 'Afbeeldingseigenschappen',
+	uploadTab: 'Uploaden',
+	urlMissing: 'De URL naar de afbeelding ontbreekt.',
+	altMissing: 'Alternatieve tekst ontbreekt.',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/no.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'no', {
+	alt: 'Alternativ tekst',
+	btnUpload: 'Send det til serveren',
+	captioned: 'Bilde med bildetekst',
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Bildeinformasjon',
+	lockRatio: 'Lås forhold',
+	menu: 'Bildeegenskaper',
+	pathName: 'bilde',
+	pathNameCaption: 'bildetekst',
+	resetSize: 'Tilbakestill størrelse',
+	resizer: 'Klikk og dra for å endre størrelse',
+	title: 'Bildeegenskaper',
+	uploadTab: 'Last opp',
+	urlMissing: 'Bildets adresse mangler.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/oc.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'oc', {
+	alt: 'Tèxte alternatiu',
+	btnUpload: 'Mandar sul servidor',
+	captioned: 'Imatge amb legenda',
+	captionPlaceholder: 'Legenda',
+	infoTab: 'Informacions sus l\'imatge',
+	lockRatio: 'Conservar las proporcions',
+	menu: 'Proprietats de l\'imatge',
+	pathName: 'imatge',
+	pathNameCaption: 'legenda',
+	resetSize: 'Reïnicializar la talha',
+	resizer: 'Clicar e lisar per redimensionar',
+	title: 'Proprietats de l\'imatge',
+	uploadTab: 'Mandar',
+	urlMissing: 'L\'URL font de l\'imatge es mancanta.',
+	altMissing: 'Lo tèxte alternatiu es mancant.',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/pl.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'pl', {
+	alt: 'Tekst zastępczy',
+	btnUpload: 'Wyślij',
+	captioned: 'Obrazek z podpisem',
+	captionPlaceholder: 'Podpis',
+	infoTab: 'Informacje o obrazku',
+	lockRatio: 'Zablokuj proporcje',
+	menu: 'Właściwości obrazka',
+	pathName: 'obrazek',
+	pathNameCaption: 'podpis',
+	resetSize: 'Przywróć rozmiar',
+	resizer: 'Kliknij i przeciągnij, by zmienić rozmiar.',
+	title: 'Właściwości obrazka',
+	uploadTab: 'Wyślij',
+	urlMissing: 'Podaj adres URL obrazka.',
+	altMissing: 'Podaj tekst zastępczy obrazka.',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/pt-br.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'pt-br', {
+	alt: 'Texto Alternativo',
+	btnUpload: 'Enviar para o Servidor',
+	captioned: 'Legenda da Imagem',
+	captionPlaceholder: 'Legenda',
+	infoTab: 'Informações da Imagem',
+	lockRatio: 'Travar Proporções',
+	menu: 'Formatar Imagem',
+	pathName: 'Imagem',
+	pathNameCaption: 'Legenda',
+	resetSize: 'Redefinir para o Tamanho Original',
+	resizer: 'Click e arraste para redimensionar',
+	title: 'Formatar Imagem',
+	uploadTab: 'Enviar ao Servidor',
+	urlMissing: 'URL da imagem está faltando.',
+	altMissing: 'Texto alternativo não informado.',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/pt.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'pt', {
+	alt: 'Texto alternativo',
+	btnUpload: 'Enviar para o servidor',
+	captioned: 'Imagem legendada',
+	captionPlaceholder: 'Legenda',
+	infoTab: 'Informação da imagem',
+	lockRatio: 'Proporcional',
+	menu: 'Propriedades da imagem',
+	pathName: 'imagem',
+	pathNameCaption: 'legenda',
+	resetSize: 'Tamanho original',
+	resizer: 'Clique e arraste para redimensionar',
+	title: 'Propriedades da imagem',
+	uploadTab: 'Carregar',
+	urlMissing: 'O URL da fonte da imagem está em falta.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ro.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'ro', {
+	alt: 'Text alternativ',
+	btnUpload: 'Trimite la server',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Informaţii despre imagine',
+	lockRatio: 'Păstrează proporţiile',
+	menu: 'Proprietăţile imaginii',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Resetează mărimea',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Proprietăţile imaginii',
+	uploadTab: 'Încarcă',
+	urlMissing: 'Sursa URL a imaginii lipsește.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ru.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'ru', {
+	alt: 'Альтернативный текст',
+	btnUpload: 'Загрузить на сервер',
+	captioned: 'Отображать название',
+	captionPlaceholder: 'Название',
+	infoTab: 'Данные об изображении',
+	lockRatio: 'Сохранять пропорции',
+	menu: 'Свойства изображения',
+	pathName: 'изображение',
+	pathNameCaption: 'название',
+	resetSize: 'Вернуть обычные размеры',
+	resizer: 'Нажмите и растяните',
+	title: 'Свойства изображения',
+	uploadTab: 'Загрузка файла',
+	urlMissing: 'Не указана ссылка на изображение.',
+	altMissing: 'Не задан альтернативный текст',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/si.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'si', {
+	alt: 'විකල්ප ',
+	btnUpload: 'සේවාදායකය වෙත යොමුකිරිම',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'රුපයේ තොරතුරු',
+	lockRatio: 'නවතන අනුපාතය ',
+	menu: 'රුපයේ ගුණ',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'නැවතත් විශාලත්වය වෙනස් කිරීම',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'රුපයේ ',
+	uploadTab: 'උඩුගතකිරීම',
+	urlMissing: 'රුප මුලාශ්‍ර URL නැත.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sk.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'sk', {
+	alt: 'Alternatívny text',
+	btnUpload: 'Odoslať to na server',
+	captioned: 'Opísaný obrázok',
+	captionPlaceholder: 'Popis',
+	infoTab: 'Informácie o obrázku',
+	lockRatio: 'Pomer zámky',
+	menu: 'Vlastnosti obrázka',
+	pathName: 'obrázok',
+	pathNameCaption: 'popis',
+	resetSize: 'Pôvodná veľkosť',
+	resizer: 'Kliknite a potiahnite pre zmenu veľkosti',
+	title: 'Vlastnosti obrázka',
+	uploadTab: 'Nahrať',
+	urlMissing: 'Chýba URL zdroja obrázka.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sl.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'sl', {
+	alt: 'Nadomestno besedilo',
+	btnUpload: 'Pošlji na strežnik',
+	captioned: 'Slika z napisom',
+	captionPlaceholder: 'Napis',
+	infoTab: 'Podatki o sliki',
+	lockRatio: 'Zakleni razmerje',
+	menu: 'Lastnosti slike',
+	pathName: 'slika',
+	pathNameCaption: 'napis',
+	resetSize: 'Ponastavi velikost',
+	resizer: 'Kliknite in povlecite, da spremenite velikost',
+	title: 'Lastnosti slike',
+	uploadTab: 'Naloži',
+	urlMissing: 'Manjka vir (URL) slike.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sq.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'sq', {
+	alt: 'Tekst Alternativ',
+	btnUpload: 'Dërgo në server',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Informacione mbi Fotografinë',
+	lockRatio: 'Mbyll Racionin',
+	menu: 'Karakteristikat e Fotografisë',
+	pathName: 'foto',
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Rikthe Madhësinë',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Karakteristikat e Fotografisë',
+	uploadTab: 'Ngarko',
+	urlMissing: 'Mungon URL e burimit të fotografisë.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sr-latn.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'sr-latn', {
+	alt: 'Alternativni tekst',
+	btnUpload: 'Pošalji na server',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Info slike',
+	lockRatio: 'Zaključaj odnos',
+	menu: 'Osobine slika',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Resetuj veličinu',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Osobine slika',
+	uploadTab: 'Pošalji',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sr.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'sr', {
+	alt: 'Алтернативни текст',
+	btnUpload: 'Пошаљи на сервер',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'Инфо слике',
+	lockRatio: 'Закључај однос',
+	menu: 'Особине слика',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'Ресетуј величину',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'Особине слика',
+	uploadTab: 'Пошаљи',
+	urlMissing: 'Недостаје УРЛ слике.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/sv.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'sv', {
+	alt: 'Alternativ text',
+	btnUpload: 'Skicka till server',
+	captioned: 'Rubricerad bild',
+	captionPlaceholder: 'Bildtext',
+	infoTab: 'Bildinformation',
+	lockRatio: 'Lås höjd/bredd förhållanden',
+	menu: 'Bildegenskaper',
+	pathName: 'bild',
+	pathNameCaption: 'rubrik',
+	resetSize: 'Återställ storlek',
+	resizer: 'Klicka och drag för att ändra storlek',
+	title: 'Bildegenskaper',
+	uploadTab: 'Ladda upp',
+	urlMissing: 'Bildkällans URL saknas.',
+	altMissing: 'Alternativ text saknas',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/th.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'th', {
+	alt: 'คำประกอบรูปภาพ',
+	btnUpload: 'อัพโหลดไฟล์ไปเก็บไว้ที่เครื่องแม่ข่าย (เซิร์ฟเวอร์)',
+	captioned: 'Captioned image', // MISSING
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'ข้อมูลของรูปภาพ',
+	lockRatio: 'กำหนดอัตราส่วน กว้าง-สูง แบบคงที่',
+	menu: 'คุณสมบัติของ รูปภาพ',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'กำหนดรูปเท่าขนาดจริง',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'คุณสมบัติของ รูปภาพ',
+	uploadTab: 'อัพโหลดไฟล์',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/tr.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'tr', {
+	alt: 'Alternatif Yazı',
+	btnUpload: 'Sunucuya Yolla',
+	captioned: 'Başlıklı resim',
+	captionPlaceholder: 'Başlık',
+	infoTab: 'Resim Bilgisi',
+	lockRatio: 'Oranı Kilitle',
+	menu: 'Resim Özellikleri',
+	pathName: 'Resim',
+	pathNameCaption: 'başlık',
+	resetSize: 'Boyutu Başa Döndür',
+	resizer: 'Boyutlandırmak için, tıklayın ve sürükleyin',
+	title: 'Resim Özellikleri',
+	uploadTab: 'Karşıya Yükle',
+	urlMissing: 'Resmin URL kaynağı bulunamadı.',
+	altMissing: 'Alternatif yazı eksik.',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/tt.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'tt', {
+	alt: 'Альтернатив текст',
+	btnUpload: 'Серверга җибәрү',
+	captioned: 'Исеме куелган рәсем',
+	captionPlaceholder: 'Исем',
+	infoTab: 'Рәсем тасвирламасы',
+	lockRatio: 'Lock Ratio', // MISSING
+	menu: 'Рәсем үзлекләре',
+	pathName: 'рәсем',
+	pathNameCaption: 'исем',
+	resetSize: 'Баштагы зурлык',
+	resizer: 'Күчереп куер өчен басып шудырыгыз',
+	title: 'Рәсем үзлекләре',
+	uploadTab: 'Йөкләү',
+	urlMissing: 'Image source URL is missing.', // MISSING
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/ug.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'ug', {
+	alt: 'تېكىست ئالماشتۇر',
+	btnUpload: 'مۇلازىمېتىرغا يۈكلە',
+	captioned: 'ماۋزۇلۇق سۈرەت',
+	captionPlaceholder: 'Caption', // MISSING
+	infoTab: 'سۈرەت',
+	lockRatio: 'نىسبەتنى قۇلۇپلا',
+	menu: 'سۈرەت خاسلىقى',
+	pathName: 'image', // MISSING
+	pathNameCaption: 'caption', // MISSING
+	resetSize: 'ئەسلى چوڭلۇق',
+	resizer: 'Click and drag to resize', // MISSING
+	title: 'سۈرەت خاسلىقى',
+	uploadTab: 'يۈكلە',
+	urlMissing: 'سۈرەتنىڭ ئەسلى ھۆججەت ئادرېسى كەم',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/uk.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'uk', {
+	alt: 'Альтернативний текст',
+	btnUpload: 'Надіслати на сервер',
+	captioned: 'Підписане зображення',
+	captionPlaceholder: 'Заголовок',
+	infoTab: 'Інформація про зображення',
+	lockRatio: 'Зберегти пропорції',
+	menu: 'Властивості зображення',
+	pathName: 'Зображення',
+	pathNameCaption: 'заголовок',
+	resetSize: 'Очистити поля розмірів',
+	resizer: 'Клікніть та потягніть для зміни розмірів',
+	title: 'Властивості зображення',
+	uploadTab: 'Надіслати',
+	urlMissing: 'Вкажіть URL зображення.',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/vi.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'vi', {
+	alt: 'Chú thích ảnh',
+	btnUpload: 'Tải lên máy chủ',
+	captioned: 'Ảnh có chú thích',
+	captionPlaceholder: 'Nhãn',
+	infoTab: 'Thông tin của ảnh',
+	lockRatio: 'Giữ nguyên tỷ lệ',
+	menu: 'Thuộc tính của ảnh',
+	pathName: 'ảnh',
+	pathNameCaption: 'chú thích',
+	resetSize: 'Kích thước gốc',
+	resizer: 'Kéo rê để thay đổi kích cỡ',
+	title: 'Thuộc tính của ảnh',
+	uploadTab: 'Tải lên',
+	urlMissing: 'Thiếu đường dẫn hình ảnh',
+	altMissing: 'Alternative text is missing.', // MISSING
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/zh-cn.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'zh-cn', {
+	alt: '替换文本',
+	btnUpload: '上传到服务器',
+	captioned: '带标题图像',
+	captionPlaceholder: '标题',
+	infoTab: '图像信息',
+	lockRatio: '锁定比例',
+	menu: '图像属性',
+	pathName: '图像',
+	pathNameCaption: '标题',
+	resetSize: '原始尺寸',
+	resizer: '点击并拖拽以改变尺寸',
+	title: '图像属性',
+	uploadTab: '上传',
+	urlMissing: '缺少图像源文件地址',
+	altMissing: '缺少替换文本',
+    responsive: 'Responsive image' // MISSING
+} );

+ 22 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/lang/zh.js

@@ -0,0 +1,22 @@
+/*
+Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.md or http://ckeditor.com/license
+*/
+CKEDITOR.plugins.setLang( 'image2_chamilo', 'zh', {
+	alt: '替代文字',
+	btnUpload: '傳送至伺服器',
+	captioned: '已加標題之圖片',
+	captionPlaceholder: '標題',
+	infoTab: '影像資訊',
+	lockRatio: '固定比例',
+	menu: '影像屬性',
+	pathName: '圖片',
+	pathNameCaption: '標題',
+	resetSize: '重設大小',
+	resizer: '拖曳以改變大小',
+	title: '影像屬性',
+	uploadTab: '上傳',
+	urlMissing: '遺失圖片來源之 URL ',
+	altMissing: '替代文字遺失。',
+    responsive: 'Responsive image' // MISSING
+} );

+ 1724 - 0
main/inc/lib/javascript/ckeditor/plugins/image2_chamilo/plugin.js

@@ -0,0 +1,1724 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or http://ckeditor.com/license
+ */
+
+'use strict';
+
+( function() {
+
+	var template = '<img alt="" src="" />',
+		templateBlock = new CKEDITOR.template(
+			'<figure class="{captionedClass}">' +
+				template +
+				'<figcaption>{captionPlaceholder}</figcaption>' +
+			'</figure>' ),
+		alignmentsObj = { left: 0, center: 1, right: 2 },
+		regexPercent = /^\s*(\d+\%)\s*$/i;
+
+	CKEDITOR.plugins.add( 'image2_chamilo', {
+		// jscs:disable maximumLineLength
+		lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
+		// jscs:enable maximumLineLength
+		requires: 'widget,dialog',
+		icons: 'image',
+		hidpi: true,
+
+		onLoad: function() {
+			CKEDITOR.addCss(
+			'.cke_image_nocaption{' +
+				// This is to remove unwanted space so resize
+				// wrapper is displayed property.
+				'line-height:0' +
+			'}' +
+			'.cke_editable.cke_image_sw, .cke_editable.cke_image_sw *{cursor:sw-resize !important}' +
+			'.cke_editable.cke_image_se, .cke_editable.cke_image_se *{cursor:se-resize !important}' +
+			'.cke_image_resizer{' +
+				'display:none;' +
+				'position:absolute;' +
+				'width:10px;' +
+				'height:10px;' +
+				'bottom:-5px;' +
+				'right:-5px;' +
+				'background:#000;' +
+				'outline:1px solid #fff;' +
+				// Prevent drag handler from being misplaced (#11207).
+				'line-height:0;' +
+				'cursor:se-resize;' +
+			'}' +
+			'.cke_image_resizer_wrapper{' +
+				'position:relative;' +
+				'display:inline-block;' +
+				'line-height:0;' +
+			'}' +
+			// Bottom-left corner style of the resizer.
+			'.cke_image_resizer.cke_image_resizer_left{' +
+				'right:auto;' +
+				'left:-5px;' +
+				'cursor:sw-resize;' +
+			'}' +
+			'.cke_widget_wrapper:hover .cke_image_resizer,' +
+			'.cke_image_resizer.cke_image_resizing{' +
+				'display:block' +
+			'}' +
+			// Expand widget wrapper when linked inline image.
+			'.cke_widget_wrapper>a{' +
+				'display:inline-block' +
+			'}' );
+		},
+
+		init: function( editor ) {
+			// Adapts configuration from original image plugin. Should be removed
+			// when we'll rename image2_chamilo to image.
+			var config = editor.config,
+				lang = editor.lang.image2_chamilo,
+				image = widgetDef( editor );
+
+			// Since filebrowser plugin discovers config properties by dialog (plugin?)
+			// names (sic!), this hack will be necessary as long as Image2Chamilo is not named
+			// Image. And since Image2Chamilo will never be Image, for sure some filebrowser logic
+			// got to be refined.
+			config.filebrowserImage2ChamiloBrowseUrl = config.filebrowserImageBrowseUrl;
+			config.filebrowserImage2ChamiloUploadUrl = config.filebrowserImageUploadUrl;
+
+			// Add custom elementspath names to widget definition.
+			image.pathName = lang.pathName;
+			image.editables.caption.pathName = lang.pathNameCaption;
+
+			// Register the widget.
+			editor.widgets.add( 'image', image );
+
+			// Add toolbar button for this plugin.
+			editor.ui.addButton && editor.ui.addButton( 'Image', {
+				label: editor.lang.common.image,
+				command: 'image',
+				toolbar: 'insert,10'
+			} );
+
+			// Register context menu option for editing widget.
+			if ( editor.contextMenu ) {
+				editor.addMenuGroup( 'image', 10 );
+
+				editor.addMenuItem( 'image', {
+					label: lang.menu,
+					command: 'image',
+					group: 'image'
+				} );
+			}
+
+			CKEDITOR.dialog.add( 'image2_chamilo', this.path + 'dialogs/image2_chamilo.js' );
+		},
+
+		afterInit: function( editor ) {
+			// Integrate with align commands (justify plugin).
+			var align = { left: 1, right: 1, center: 1, block: 1 },
+				integrate = alignCommandIntegrator( editor );
+
+			for ( var value in align )
+				integrate( value );
+
+			// Integrate with link commands (link plugin).
+			linkCommandIntegrator( editor );
+		}
+	} );
+
+	// Wiget states (forms) depending on alignment and configuration.
+	//
+	// Non-captioned widget (inline styles)
+	// 		┌──────┬───────────────────────────────┬─────────────────────────────┐
+	// 		│Align │Internal form                  │Data                         │
+	// 		├──────┼───────────────────────────────┼─────────────────────────────┤
+	// 		│none  │<wrapper>                      │<img />                      │
+	// 		│      │ <img />                       │                             │
+	// 		│      │</wrapper>                     │                             │
+	// 		├──────┼───────────────────────────────┼─────────────────────────────┤
+	// 		│left  │<wrapper style=”float:left”>   │<img style=”float:left” />   │
+	// 		│      │ <img />                       │                             │
+	// 		│      │</wrapper>                     │                             │
+	// 		├──────┼───────────────────────────────┼─────────────────────────────┤
+	// 		│center│<wrapper>                      │<p style=”text-align:center”>│
+	// 		│      │ <p style=”text-align:center”> │  <img />                    │
+	// 		│      │   <img />                     │</p>                         │
+	// 		│      │ </p>                          │                             │
+	// 		│      │</wrapper>                     │                             │
+	// 		├──────┼───────────────────────────────┼─────────────────────────────┤
+	// 		│right │<wrapper style=”float:right”>  │<img style=”float:right” />  │
+	// 		│      │ <img />                       │                             │
+	// 		│      │</wrapper>                     │                             │
+	// 		└──────┴───────────────────────────────┴─────────────────────────────┘
+	//
+	// Non-captioned widget (config.image2_chamilo_alignClasses defined)
+	// 		┌──────┬───────────────────────────────┬─────────────────────────────┐
+	// 		│Align │Internal form                  │Data                         │
+	// 		├──────┼───────────────────────────────┼─────────────────────────────┤
+	// 		│none  │<wrapper>                      │<img />                      │
+	// 		│      │ <img />                       │                             │
+	// 		│      │</wrapper>                     │                             │
+	// 		├──────┼───────────────────────────────┼─────────────────────────────┤
+	// 		│left  │<wrapper class=”left”>         │<img class=”left” />         │
+	// 		│      │ <img />                       │                             │
+	// 		│      │</wrapper>                     │                             │
+	// 		├──────┼───────────────────────────────┼─────────────────────────────┤
+	// 		│center│<wrapper>                      │<p class=”center”>           │
+	// 		│      │ <p class=”center”>            │ <img />                     │
+	// 		│      │   <img />                     │</p>                         │
+	// 		│      │ </p>                          │                             │
+	// 		│      │</wrapper>                     │                             │
+	// 		├──────┼───────────────────────────────┼─────────────────────────────┤
+	// 		│right │<wrapper class=”right”>        │<img class=”right” />        │
+	// 		│      │ <img />                       │                             │
+	// 		│      │</wrapper>                     │                             │
+	// 		└──────┴───────────────────────────────┴─────────────────────────────┘
+	//
+	// Captioned widget (inline styles)
+	// 		┌──────┬────────────────────────────────────────┬────────────────────────────────────────┐
+	// 		│Align │Internal form                           │Data                                    │
+	// 		├──────┼────────────────────────────────────────┼────────────────────────────────────────┤
+	// 		│none  │<wrapper>                               │<figure />                              │
+	// 		│      │ <figure />                             │                                        │
+	// 		│      │</wrapper>                              │                                        │
+	// 		├──────┼────────────────────────────────────────┼────────────────────────────────────────┤
+	// 		│left  │<wrapper style=”float:left”>            │<figure style=”float:left” />           │
+	// 		│      │ <figure />                             │                                        │
+	// 		│      │</wrapper>                              │                                        │
+	// 		├──────┼────────────────────────────────────────┼────────────────────────────────────────┤
+	// 		│center│<wrapper style=”text-align:center”>     │<div style=”text-align:center”>         │
+	// 		│      │ <figure style=”display:inline-block” />│ <figure style=”display:inline-block” />│
+	// 		│      │</wrapper>                              │</p>                                    │
+	// 		├──────┼────────────────────────────────────────┼────────────────────────────────────────┤
+	// 		│right │<wrapper style=”float:right”>           │<figure style=”float:right” />          │
+	// 		│      │ <figure />                             │                                        │
+	// 		│      │</wrapper>                              │                                        │
+	// 		└──────┴────────────────────────────────────────┴────────────────────────────────────────┘
+	//
+	// Captioned widget (config.image2_chamilo_alignClasses defined)
+	// 		┌──────┬────────────────────────────────────────┬────────────────────────────────────────┐
+	// 		│Align │Internal form                           │Data                                    │
+	// 		├──────┼────────────────────────────────────────┼────────────────────────────────────────┤
+	// 		│none  │<wrapper>                               │<figure />                              │
+	// 		│      │ <figure />                             │                                        │
+	// 		│      │</wrapper>                              │                                        │
+	// 		├──────┼────────────────────────────────────────┼────────────────────────────────────────┤
+	// 		│left  │<wrapper class=”left”>                  │<figure class=”left” />                 │
+	// 		│      │ <figure />                             │                                        │
+	// 		│      │</wrapper>                              │                                        │
+	// 		├──────┼────────────────────────────────────────┼────────────────────────────────────────┤
+	// 		│center│<wrapper class=”center”>                │<div class=”center”>                    │
+	// 		│      │ <figure />                             │ <figure />                             │
+	// 		│      │</wrapper>                              │</p>                                    │
+	// 		├──────┼────────────────────────────────────────┼────────────────────────────────────────┤
+	// 		│right │<wrapper class=”right”>                 │<figure class=”right” />                │
+	// 		│      │ <figure />                             │                                        │
+	// 		│      │</wrapper>                              │                                        │
+	// 		└──────┴────────────────────────────────────────┴────────────────────────────────────────┘
+	//
+	// @param {CKEDITOR.editor}
+	// @returns {Object}
+	function widgetDef( editor ) {
+		var alignClasses = editor.config.image2_chamilo_alignClasses,
+			captionedClass = editor.config.image2_chamilo_captionedClass;
+
+		function deflate() {
+			if ( this.deflated )
+				return;
+
+			// Remember whether widget was focused before destroyed.
+			if ( editor.widgets.focused == this.widget )
+				this.focused = true;
+
+			editor.widgets.destroy( this.widget );
+
+			// Mark widget was destroyed.
+			this.deflated = true;
+		}
+
+		function inflate() {
+			var editable = editor.editable(),
+			doc = editor.document;
+
+			// Create a new widget. This widget will be either captioned
+			// non-captioned, block or inline according to what is the
+			// new state of the widget.
+			if ( this.deflated ) {
+				this.widget = editor.widgets.initOn( this.element, 'image', this.widget.data );
+
+				// Once widget was re-created, it may become an inline element without
+				// block wrapper (i.e. when unaligned, end not captioned). Let's do some
+				// sort of autoparagraphing here (#10853).
+				if ( this.widget.inline && !( new CKEDITOR.dom.elementPath( this.widget.wrapper, editable ).block ) ) {
+					var block = doc.createElement( editor.activeEnterMode == CKEDITOR.ENTER_P ? 'p' : 'div' );
+					block.replace( this.widget.wrapper );
+					this.widget.wrapper.move( block );
+				}
+
+				// The focus must be transferred from the old one (destroyed)
+				// to the new one (just created).
+				if ( this.focused ) {
+					this.widget.focus();
+					delete this.focused;
+				}
+
+				delete this.deflated;
+			}
+
+			// If now widget was destroyed just update wrapper's alignment.
+			// According to the new state.
+			else {
+				setWrapperAlign( this.widget, alignClasses );
+			}
+		}
+
+		return {
+			allowedContent: getWidgetAllowedContent( editor ),
+
+			requiredContent: 'img[src,alt]',
+
+			features: getWidgetFeatures( editor ),
+
+			styleableElements: 'img figure',
+
+			// This widget converts style-driven dimensions to attributes.
+			contentTransformations: [
+				[ 'img[width]: sizeToAttribute' ]
+			],
+
+			// This widget has an editable caption.
+			editables: {
+				caption: {
+					selector: 'figcaption',
+					allowedContent: 'br em strong sub sup u s; a[!href,target]'
+				}
+			},
+
+			parts: {
+				image: 'img',
+				caption: 'figcaption'
+				// parts#link defined in widget#init
+			},
+
+			// The name of this widget's dialog.
+			dialog: 'image2_chamilo',
+
+			// Template of the widget: plain image.
+			template: template,
+
+			data: function() {
+				var features = this.features;
+
+				// Image can't be captioned when figcaption is disallowed (#11004).
+				if ( this.data.hasCaption && !editor.filter.checkFeature( features.caption ) )
+					this.data.hasCaption = false;
+
+				// Image can't be aligned when floating is disallowed (#11004).
+				if ( this.data.align != 'none' && !editor.filter.checkFeature( features.align ) )
+					this.data.align = 'none';
+
+				// Convert the internal form of the widget from the old state to the new one.
+				this.shiftState( {
+					widget: this,
+					element: this.element,
+					oldData: this.oldData,
+					newData: this.data,
+					deflate: deflate,
+					inflate: inflate
+				} );
+
+				// Update widget.parts.link since it will not auto-update unless widget
+				// is destroyed and re-inited.
+				if ( !this.data.link ) {
+					if ( this.parts.link )
+						delete this.parts.link;
+				} else {
+					if ( !this.parts.link )
+						this.parts.link = this.parts.image.getParent();
+				}
+
+				this.parts.image.setAttributes( {
+					src: this.data.src,
+					class: this.data.isResponsive ? 'img-responsive' : '',
+
+					// This internal is required by the editor.
+					'data-cke-saved-src': this.data.src,
+
+					alt: this.data.alt
+				} );
+
+				// If shifting non-captioned -> captioned, remove classes
+				// related to styles from <img/>.
+				if ( this.oldData && !this.oldData.hasCaption && this.data.hasCaption ) {
+					for ( var c in this.data.classes )
+						this.parts.image.removeClass( c );
+				}
+
+				// Set dimensions of the image according to gathered data.
+				// Do it only when the attributes are allowed (#11004).
+				if ( editor.filter.checkFeature( features.dimension ) )
+					setDimensions( this );
+
+				// Cache current data.
+				this.oldData = CKEDITOR.tools.extend( {}, this.data );
+			},
+
+			init: function() {
+				var helpers = CKEDITOR.plugins.image2_chamilo,
+					image = this.parts.image,
+					data = {
+						hasCaption: !!this.parts.caption,
+						src: image.getAttribute( 'src' ),
+						alt: image.getAttribute( 'alt' ) || '',
+						width: image.getAttribute( 'width' ) || '',
+						height: image.getAttribute( 'height' ) || '',
+						isResponsive: !!image.$.className.match(/img-responsive/i),
+						// Lock ratio is on by default (#10833).
+						lock: this.ready ? helpers.checkHasNaturalRatio( image ) : true
+					};
+
+				// If we used 'a' in widget#parts definition, it could happen that
+				// selected element is a child of widget.parts#caption. Since there's no clever
+				// way to solve it with CSS selectors, it's done like that. (#11783).
+				var link = image.getAscendant( 'a' );
+
+				if ( link && this.wrapper.contains( link ) )
+					this.parts.link = link;
+
+				// Depending on configuration, read style/class from element and
+				// then remove it. Removed style/class will be set on wrapper in #data listener.
+				// Note: Center alignment is detected during upcast, so only left/right cases
+				// are checked below.
+				if ( !data.align ) {
+					var alignElement = data.hasCaption ? this.element : image;
+
+					// Read the initial left/right alignment from the class set on element.
+					if ( alignClasses ) {
+						if ( alignElement.hasClass( alignClasses[ 0 ] ) ) {
+							data.align = 'left';
+						} else if ( alignElement.hasClass( alignClasses[ 2 ] ) ) {
+							data.align = 'right';
+						}
+
+						if ( data.align ) {
+							alignElement.removeClass( alignClasses[ alignmentsObj[ data.align ] ] );
+						} else {
+							data.align = 'none';
+						}
+					}
+					// Read initial float style from figure/image and then remove it.
+					else {
+						data.align = alignElement.getStyle( 'float' ) || 'none';
+						alignElement.removeStyle( 'float' );
+					}
+				}
+
+				// Update data.link object with attributes if the link has been discovered.
+				if ( editor.plugins.link && this.parts.link ) {
+					data.link = helpers.getLinkAttributesParser()( editor, this.parts.link );
+
+					// Get rid of cke_widget_* classes in data. Otherwise
+					// they might appear in link dialog.
+					var advanced = data.link.advanced;
+					if ( advanced && advanced.advCSSClasses ) {
+						advanced.advCSSClasses = CKEDITOR.tools.trim( advanced.advCSSClasses.replace( /cke_\S+/, '' ) );
+					}
+				}
+
+				// Get rid of extra vertical space when there's no caption.
+				// It will improve the look of the resizer.
+				this.wrapper[ ( data.hasCaption ? 'remove' : 'add' ) + 'Class' ]( 'cke_image_nocaption' );
+
+				this.setData( data );
+
+				// Setup dynamic image resizing with mouse.
+				// Don't initialize resizer when dimensions are disallowed (#11004).
+				if ( editor.filter.checkFeature( this.features.dimension ) && editor.config.image2_chamilo_disableResizer !== true )
+					setupResizer( this );
+
+				this.shiftState = helpers.stateShifter( this.editor );
+
+				// Add widget editing option to its context menu.
+				this.on( 'contextMenu', function( evt ) {
+					evt.data.image = CKEDITOR.TRISTATE_OFF;
+
+					// Integrate context menu items for link.
+					// Note that widget may be wrapped in a link, which
+					// does not belong to that widget (#11814).
+					if ( this.parts.link || this.wrapper.getAscendant( 'a' ) )
+						evt.data.link = evt.data.unlink = CKEDITOR.TRISTATE_OFF;
+				} );
+
+				// Pass the reference to this widget to the dialog.
+				this.on( 'dialog', function( evt ) {
+					evt.data.widget = this;
+				}, this );
+			},
+
+			// Overrides default method to handle internal mutability of Image2Chamilo.
+			// @see CKEDITOR.plugins.widget#addClass
+			addClass: function( className ) {
+				getStyleableElement( this ).addClass( className );
+			},
+
+			// Overrides default method to handle internal mutability of Image2Chamilo.
+			// @see CKEDITOR.plugins.widget#hasClass
+			hasClass: function( className ) {
+				return getStyleableElement( this ).hasClass( className );
+			},
+
+			// Overrides default method to handle internal mutability of Image2Chamilo.
+			// @see CKEDITOR.plugins.widget#removeClass
+			removeClass: function( className ) {
+				getStyleableElement( this ).removeClass( className );
+			},
+
+			// Overrides default method to handle internal mutability of Image2Chamilo.
+			// @see CKEDITOR.plugins.widget#getClasses
+			getClasses: ( function() {
+				var classRegex = new RegExp( '^(' + [].concat( captionedClass, alignClasses ).join( '|' ) + ')$' );
+
+				return function() {
+					var classes = this.repository.parseElementClasses( getStyleableElement( this ).getAttribute( 'class' ) );
+
+					// Neither config.image2_chamilo_captionedClass nor config.image2_chamilo_alignClasses
+					// do not belong to style classes.
+					for ( var c in classes ) {
+						if ( classRegex.test( c ) )
+							delete classes[ c ];
+					}
+
+					return classes;
+				};
+			} )(),
+
+			upcast: upcastWidgetElement( editor ),
+			downcast: downcastWidgetElement( editor ),
+
+			getLabel: function() {
+				var label = ( this.data.alt || '' ) + ' ' + this.pathName;
+
+				return this.editor.lang.widget.label.replace( /%1/, label );
+			}
+		};
+	}
+
+	/**
+	 * A set of Enhanced Image (image2_chamilo) plugin helpers.
+	 *
+	 * @class
+	 * @singleton
+	 */
+	CKEDITOR.plugins.image2_chamilo = {
+		stateShifter: function( editor ) {
+			// Tag name used for centering non-captioned widgets.
+			var doc = editor.document,
+				alignClasses = editor.config.image2_chamilo_alignClasses,
+				captionedClass = editor.config.image2_chamilo_captionedClass,
+				editable = editor.editable(),
+
+				// The order that stateActions get executed. It matters!
+				shiftables = [ 'hasCaption', 'align', 'link' ];
+
+			// Atomic procedures, one per state variable.
+			var stateActions = {
+				align: function( shift, oldValue, newValue ) {
+					var el = shift.element;
+
+					// Alignment changed.
+					if ( shift.changed.align ) {
+						// No caption in the new state.
+						if ( !shift.newData.hasCaption ) {
+							// Changed to "center" (non-captioned).
+							if ( newValue == 'center' ) {
+								shift.deflate();
+								shift.element = wrapInCentering( editor, el );
+							}
+
+							// Changed to "non-center" from "center" while caption removed.
+							if ( !shift.changed.hasCaption && oldValue == 'center' && newValue != 'center' ) {
+								shift.deflate();
+								shift.element = unwrapFromCentering( el );
+							}
+						}
+					}
+
+					// Alignment remains and "center" removed caption.
+					else if ( newValue == 'center' && shift.changed.hasCaption && !shift.newData.hasCaption ) {
+						shift.deflate();
+						shift.element = wrapInCentering( editor, el );
+					}
+
+					// Finally set display for figure.
+					if ( !alignClasses && el.is( 'figure' ) ) {
+						if ( newValue == 'center' )
+							el.setStyle( 'display', 'inline-block' );
+						else
+							el.removeStyle( 'display' );
+					}
+				},
+
+				hasCaption:	function( shift, oldValue, newValue ) {
+					// This action is for real state change only.
+					if ( !shift.changed.hasCaption )
+						return;
+
+					// Get <img/> or <a><img/></a> from widget. Note that widget element might itself
+					// be what we're looking for. Also element can be <p style="text-align:center"><a>...</a></p>.
+					var imageOrLink;
+					if ( shift.element.is( { img: 1, a: 1 } ) )
+						imageOrLink = shift.element;
+					else
+						imageOrLink =  shift.element.findOne( 'a,img' );
+
+					// Switching hasCaption always destroys the widget.
+					shift.deflate();
+
+					// There was no caption, but the caption is to be added.
+					if ( newValue ) {
+						// Create new <figure> from widget template.
+						var figure = CKEDITOR.dom.element.createFromHtml( templateBlock.output( {
+							captionedClass: captionedClass,
+							captionPlaceholder: editor.lang.image2_chamilo.captionPlaceholder
+						} ), doc );
+
+						// Replace element with <figure>.
+						replaceSafely( figure, shift.element );
+
+						// Use old <img/> or <a><img/></a> instead of the one from the template,
+						// so we won't lose additional attributes.
+						imageOrLink.replace( figure.findOne( 'img' ) );
+
+						// Update widget's element.
+						shift.element = figure;
+					}
+
+					// The caption was present, but now it's to be removed.
+					else {
+						// Unwrap <img/> or <a><img/></a> from figure.
+						imageOrLink.replace( shift.element );
+
+						// Update widget's element.
+						shift.element = imageOrLink;
+					}
+				},
+
+				link: function( shift, oldValue, newValue ) {
+					if ( shift.changed.link ) {
+						var img = shift.element.is( 'img' ) ?
+								shift.element : shift.element.findOne( 'img' ),
+							link = shift.element.is( 'a' ) ?
+								shift.element : shift.element.findOne( 'a' ),
+							// Why deflate:
+							// If element is <img/>, it will be wrapped into <a>,
+							// which becomes a new widget.element.
+							// If element is <a><img/></a>, it will be unlinked
+							// so <img/> becomes a new widget.element.
+							needsDeflate = ( shift.element.is( 'a' ) && !newValue ) || ( shift.element.is( 'img' ) && newValue ),
+							newEl;
+
+						if ( needsDeflate )
+							shift.deflate();
+
+						// If unlinked the image, returned element is <img>.
+						if ( !newValue )
+							newEl = unwrapFromLink( link );
+						else {
+							// If linked the image, returned element is <a>.
+							if ( !oldValue )
+								newEl = wrapInLink( img, shift.newData.link );
+
+							// Set and remove all attributes associated with this state.
+							var attributes = CKEDITOR.plugins.image2_chamilo.getLinkAttributesGetter()( editor, newValue );
+
+							if ( !CKEDITOR.tools.isEmpty( attributes.set ) )
+								( newEl || link ).setAttributes( attributes.set );
+
+							if ( attributes.removed.length )
+								( newEl || link ).removeAttributes( attributes.removed );
+						}
+
+						if ( needsDeflate )
+							shift.element = newEl;
+					}
+				},
+
+				isResponsive: function (shift, oldValue, newValue) {
+					if (!shift.changed.isResponsive) {
+						return;
+					}
+
+                    var image = shift.element.find('img');
+				}
+			};
+
+			function wrapInCentering( editor, element ) {
+				var attribsAndStyles = {};
+
+				if ( alignClasses )
+					attribsAndStyles.attributes = { 'class': alignClasses[ 1 ] };
+				else
+					attribsAndStyles.styles = { 'text-align': 'center' };
+
+				// There's no gentle way to center inline element with CSS, so create p/div
+				// that wraps widget contents and does the trick either with style or class.
+				var center = doc.createElement(
+					editor.activeEnterMode == CKEDITOR.ENTER_P ? 'p' : 'div', attribsAndStyles );
+
+				// Replace element with centering wrapper.
+				replaceSafely( center, element );
+				element.move( center );
+
+				return center;
+			}
+
+			function unwrapFromCentering( element ) {
+				var imageOrLink = element.findOne( 'a,img' );
+
+				imageOrLink.replace( element );
+
+				return imageOrLink;
+			}
+
+			// Wraps <img/> -> <a><img/></a>.
+			// Returns reference to <a>.
+			//
+			// @param {CKEDITOR.dom.element} img
+			// @param {Object} linkData
+			// @returns {CKEDITOR.dom.element}
+			function wrapInLink( img, linkData ) {
+				var link = doc.createElement( 'a', {
+					attributes: {
+						href: linkData.url
+					}
+				} );
+
+				link.replace( img );
+				img.move( link );
+
+				return link;
+			}
+
+			// De-wraps <a><img/></a> -> <img/>.
+			// Returns the reference to <img/>
+			//
+			// @param {CKEDITOR.dom.element} link
+			// @returns {CKEDITOR.dom.element}
+			function unwrapFromLink( link ) {
+				var img = link.findOne( 'img' );
+
+				img.replace( link );
+
+				return img;
+			}
+
+			function replaceSafely( replacing, replaced ) {
+				if ( replaced.getParent() ) {
+					var range = editor.createRange();
+
+					range.moveToPosition( replaced, CKEDITOR.POSITION_BEFORE_START );
+
+					// Remove old element. Do it before insertion to avoid a case when
+					// element is moved from 'replaced' element before it, what creates
+					// a tricky case which insertElementIntorRange does not handle.
+					replaced.remove();
+
+					editable.insertElementIntoRange( replacing, range );
+				}
+				else {
+					replacing.replace( replaced );
+				}
+			}
+
+			return function( shift ) {
+				var name, i;
+
+				shift.changed = {};
+
+				for ( i = 0; i < shiftables.length; i++ ) {
+					name = shiftables[ i ];
+
+					shift.changed[ name ] = shift.oldData ?
+						shift.oldData[ name ] !== shift.newData[ name ] : false;
+				}
+
+				// Iterate over possible state variables.
+				for ( i = 0; i < shiftables.length; i++ ) {
+					name = shiftables[ i ];
+
+					stateActions[ name ]( shift,
+						shift.oldData ? shift.oldData[ name ] : null,
+						shift.newData[ name ] );
+				}
+
+				shift.inflate();
+			};
+		},
+
+		/**
+		 * Checks whether the current image ratio matches the natural one
+		 * by comparing dimensions.
+		 *
+		 * @param {CKEDITOR.dom.element} image
+		 * @returns {Boolean}
+		 */
+		checkHasNaturalRatio: function( image ) {
+			var $ = image.$,
+				natural = this.getNatural( image );
+
+			// The reason for two alternative comparisons is that the rounding can come from
+			// both dimensions, e.g. there are two cases:
+			// 	1. height is computed as a rounded relation of the real height and the value of width,
+			//	2. width is computed as a rounded relation of the real width and the value of heigh.
+			return Math.round( $.clientWidth / natural.width * natural.height ) == $.clientHeight ||
+				Math.round( $.clientHeight / natural.height * natural.width ) == $.clientWidth;
+		},
+
+		/**
+		 * Returns natural dimensions of the image. For modern browsers
+		 * it uses natural(Width|Height). For old ones (IE8) it creates
+		 * a new image and reads the dimensions.
+		 *
+		 * @param {CKEDITOR.dom.element} image
+		 * @returns {Object}
+		 */
+		getNatural: function( image ) {
+			var dimensions;
+
+			if ( image.$.naturalWidth ) {
+				dimensions = {
+					width: image.$.naturalWidth,
+					height: image.$.naturalHeight
+				};
+			} else {
+				var img = new Image();
+				img.src = image.getAttribute( 'src' );
+
+				dimensions = {
+					width: img.width,
+					height: img.height
+				};
+			}
+
+			return dimensions;
+		},
+
+		/**
+		 * Returns an attribute getter function. Default getter comes from the Link plugin
+		 * and is documented by {@link CKEDITOR.plugins.link#getLinkAttributes}.
+		 *
+		 * **Note:** It is possible to override this method and use a custom getter e.g.
+		 * in the absence of the Link plugin.
+		 *
+		 * **Note:** If a custom getter is used, a data model format it produces
+		 * must be compatible with {@link CKEDITOR.plugins.link#getLinkAttributes}.
+		 *
+		 * **Note:** A custom getter must understand the data model format produced by
+		 * {@link #getLinkAttributesParser} to work correctly.
+		 *
+		 * @returns {Function} A function that gets (composes) link attributes.
+		 * @since 4.5.5
+		 */
+		getLinkAttributesGetter: function() {
+			// #13885
+			return CKEDITOR.plugins.link.getLinkAttributes;
+		},
+
+		/**
+		 * Returns an attribute parser function. Default parser comes from the Link plugin
+		 * and is documented by {@link CKEDITOR.plugins.link#parseLinkAttributes}.
+		 *
+		 * **Note:** It is possible to override this method and use a custom parser e.g.
+		 * in the absence of the Link plugin.
+		 *
+		 * **Note:** If a custom parser is used, a data model format produced by the parser
+		 * must be compatible with {@link #getLinkAttributesGetter}.
+		 *
+		 * **Note:** If a custom parser is used, it should be compatible with the
+		 * {@link CKEDITOR.plugins.link#parseLinkAttributes} data model format. Otherwise the
+		 * Link plugin dialog may not be populated correctly with parsed data. However
+		 * as long as Enhanced Image is **not** used with the Link plugin dialog, any custom data model
+		 * will work, being stored as an internal property of Enhanced Image widget's data only.
+		 *
+		 * @returns {Function} A function that parses attributes.
+		 * @since 4.5.5
+		 */
+		getLinkAttributesParser: function() {
+			// #13885
+			return CKEDITOR.plugins.link.parseLinkAttributes;
+		}
+	};
+
+	function setWrapperAlign( widget, alignClasses ) {
+		var wrapper = widget.wrapper,
+			align = widget.data.align,
+			hasCaption = widget.data.hasCaption;
+
+		if ( alignClasses ) {
+			// Remove all align classes first.
+			for ( var i = 3; i--; )
+				wrapper.removeClass( alignClasses[ i ] );
+
+			if ( align == 'center' ) {
+				// Avoid touching non-captioned, centered widgets because
+				// they have the class set on the element instead of wrapper:
+				//
+				// 	<div class="cke_widget_wrapper">
+				// 		<p class="center-class">
+				// 			<img />
+				// 		</p>
+				// 	</div>
+				if ( hasCaption ) {
+					wrapper.addClass( alignClasses[ 1 ] );
+				}
+			} else if ( align != 'none' ) {
+				wrapper.addClass( alignClasses[ alignmentsObj[ align ] ] );
+			}
+		} else {
+			if ( align == 'center' ) {
+				if ( hasCaption )
+					wrapper.setStyle( 'text-align', 'center' );
+				else
+					wrapper.removeStyle( 'text-align' );
+
+				wrapper.removeStyle( 'float' );
+			}
+			else {
+				if ( align == 'none' )
+					wrapper.removeStyle( 'float' );
+				else
+					wrapper.setStyle( 'float', align );
+
+				wrapper.removeStyle( 'text-align' );
+			}
+		}
+	}
+
+	// Returns a function that creates widgets from all <img> and
+	// <figure class="{config.image2_chamilo_captionedClass}"> elements.
+	//
+	// @param {CKEDITOR.editor} editor
+	// @returns {Function}
+	function upcastWidgetElement( editor ) {
+		var isCenterWrapper = centerWrapperChecker( editor ),
+			captionedClass = editor.config.image2_chamilo_captionedClass;
+
+		// @param {CKEDITOR.htmlParser.element} el
+		// @param {Object} data
+		return function( el, data ) {
+			var dimensions = { width: 1, height: 1 },
+				name = el.name,
+				image;
+
+			// #11110 Don't initialize on pasted fake objects.
+			if ( el.attributes[ 'data-cke-realelement' ] )
+				return;
+
+			// If a center wrapper is found, there are 3 possible cases:
+			//
+			// 1. <div style="text-align:center"><figure>...</figure></div>.
+			//    In this case centering is done with a class set on widget.wrapper.
+			//    Simply replace centering wrapper with figure (it's no longer necessary).
+			//
+			// 2. <p style="text-align:center"><img/></p>.
+			//    Nothing to do here: <p> remains for styling purposes.
+			//
+			// 3. <div style="text-align:center"><img/></div>.
+			//    Nothing to do here (2.) but that case is only possible in enterMode different
+			//    than ENTER_P.
+			if ( isCenterWrapper( el ) ) {
+				if ( name == 'div' ) {
+					var figure = el.getFirst( 'figure' );
+
+					// Case #1.
+					if ( figure ) {
+						el.replaceWith( figure );
+						el = figure;
+					}
+				}
+				// Cases #2 and #3 (handled transparently)
+
+				// If there's a centering wrapper, save it in data.
+				data.align = 'center';
+
+				// Image can be wrapped in link <a><img/></a>.
+				image = el.getFirst( 'img' ) || el.getFirst( 'a' ).getFirst( 'img' );
+			}
+
+			// No center wrapper has been found.
+			else if ( name == 'figure' && el.hasClass( captionedClass ) ) {
+				image = el.getFirst( 'img' ) || el.getFirst( 'a' ).getFirst( 'img' );
+
+				// Upcast linked image like <a><img/></a>.
+			} else if ( isLinkedOrStandaloneImage( el ) ) {
+				image = el.name == 'a' ? el.children[ 0 ] : el;
+			}
+
+			if ( !image )
+				return;
+
+			// If there's an image, then cool, we got a widget.
+			// Now just remove dimension attributes expressed with %.
+			for ( var d in dimensions ) {
+				var dimension = image.attributes[ d ];
+
+				if ( dimension && dimension.match( regexPercent ) )
+					delete image.attributes[ d ];
+			}
+
+			return el;
+		};
+	}
+
+	// Returns a function which transforms the widget to the external format
+	// according to the current configuration.
+	//
+	// @param {CKEDITOR.editor}
+	function downcastWidgetElement( editor ) {
+		var alignClasses = editor.config.image2_chamilo_alignClasses;
+
+		// @param {CKEDITOR.htmlParser.element} el
+		return function( el ) {
+			// In case of <a><img/></a>, <img/> is the element to hold
+			// inline styles or classes (image2_chamilo_alignClasses).
+			var attrsHolder = el.name == 'a' ? el.getFirst() : el,
+				attrs = attrsHolder.attributes,
+				align = this.data.align;
+
+			// De-wrap the image from resize handle wrapper.
+			// Only block widgets have one.
+			if ( !this.inline ) {
+				var resizeWrapper = el.getFirst( 'span' );
+
+				if ( resizeWrapper )
+					resizeWrapper.replaceWith( resizeWrapper.getFirst( { img: 1, a: 1 } ) );
+			}
+
+			if ( align && align != 'none' ) {
+				var styles = CKEDITOR.tools.parseCssText( attrs.style || '' );
+
+				// When the widget is captioned (<figure>) and internally centering is done
+				// with widget's wrapper style/class, in the external data representation,
+				// <figure> must be wrapped with an element holding an style/class:
+				//
+				// 	<div style="text-align:center">
+				// 		<figure class="image" style="display:inline-block">...</figure>
+				// 	</div>
+				// or
+				// 	<div class="some-center-class">
+				// 		<figure class="image">...</figure>
+				// 	</div>
+				//
+				if ( align == 'center' && el.name == 'figure' ) {
+					el = el.wrapWith( new CKEDITOR.htmlParser.element( 'div',
+						alignClasses ? { 'class': alignClasses[ 1 ] } : { style: 'text-align:center' } ) );
+				}
+
+				// If left/right, add float style to the downcasted element.
+				else if ( align in { left: 1, right: 1 } ) {
+					if ( alignClasses )
+						attrsHolder.addClass( alignClasses[ alignmentsObj[ align ] ] );
+					else
+						styles[ 'float' ] = align;
+				}
+
+				// Update element styles.
+				if ( !alignClasses && !CKEDITOR.tools.isEmpty( styles ) )
+					attrs.style = CKEDITOR.tools.writeCssText( styles );
+			}
+
+			return el;
+		};
+	}
+
+	// Returns a function that checks if an element is a centering wrapper.
+	//
+	// @param {CKEDITOR.editor} editor
+	// @returns {Function}
+	function centerWrapperChecker( editor ) {
+		var captionedClass = editor.config.image2_chamilo_captionedClass,
+			alignClasses = editor.config.image2_chamilo_alignClasses,
+			validChildren = { figure: 1, a: 1, img: 1 };
+
+		return function( el ) {
+			// Wrapper must be either <div> or <p>.
+			if ( !( el.name in { div: 1, p: 1 } ) )
+				return false;
+
+			var children = el.children;
+
+			// Centering wrapper can have only one child.
+			if ( children.length !== 1 )
+				return false;
+
+			var child = children[ 0 ];
+
+			// Only <figure> or <img /> can be first (only) child of centering wrapper,
+			// regardless of its type.
+			if ( !( child.name in validChildren ) )
+				return false;
+
+			// If centering wrapper is <p>, only <img /> can be the child.
+			//   <p style="text-align:center"><img /></p>
+			if ( el.name == 'p' ) {
+				if ( !isLinkedOrStandaloneImage( child ) )
+					return false;
+			}
+			// Centering <div> can hold <img/> or <figure>, depending on enterMode.
+			else {
+				// If a <figure> is the first (only) child, it must have a class.
+				//   <div style="text-align:center"><figure>...</figure><div>
+				if ( child.name == 'figure' ) {
+					if ( !child.hasClass( captionedClass ) )
+						return false;
+				} else {
+					// Centering <div> can hold <img/> or <a><img/></a> only when enterMode
+					// is ENTER_(BR|DIV).
+					//   <div style="text-align:center"><img /></div>
+					//   <div style="text-align:center"><a><img /></a></div>
+					if ( editor.enterMode == CKEDITOR.ENTER_P )
+						return false;
+
+					// Regardless of enterMode, a child which is not <figure> must be
+					// either <img/> or <a><img/></a>.
+					if ( !isLinkedOrStandaloneImage( child ) )
+						return false;
+				}
+			}
+
+			// Centering wrapper got to be... centering. If image2_chamilo_alignClasses are defined,
+			// check for centering class. Otherwise, check the style.
+			if ( alignClasses ? el.hasClass( alignClasses[ 1 ] ) :
+					CKEDITOR.tools.parseCssText( el.attributes.style || '', true )[ 'text-align' ] == 'center' )
+				return true;
+
+			return false;
+		};
+	}
+
+	// Checks whether element is <img/> or <a><img/></a>.
+	//
+	// @param {CKEDITOR.htmlParser.element}
+	function isLinkedOrStandaloneImage( el ) {
+		if ( el.name == 'img' )
+			return true;
+		else if ( el.name == 'a' )
+			return el.children.length == 1 && el.getFirst( 'img' );
+
+		return false;
+	}
+
+	// Sets width and height of the widget image according to current widget data.
+	//
+	// @param {CKEDITOR.plugins.widget} widget
+	function setDimensions( widget ) {
+		var data = widget.data,
+			dimensions = { width: data.width, height: data.height },
+			image = widget.parts.image;
+
+		for ( var d in dimensions ) {
+			if ( dimensions[ d ] )
+				image.setAttribute( d, dimensions[ d ] );
+			else
+				image.removeAttribute( d );
+		}
+	}
+
+	// Defines all features related to drag-driven image resizing.
+	//
+	// @param {CKEDITOR.plugins.widget} widget
+	function setupResizer( widget ) {
+		var editor = widget.editor,
+			editable = editor.editable(),
+			doc = editor.document,
+
+			// Store the resizer in a widget for testing (#11004).
+			resizer = widget.resizer = doc.createElement( 'span' );
+
+		resizer.addClass( 'cke_image_resizer' );
+		resizer.setAttribute( 'title', editor.lang.image2_chamilo.resizer );
+		resizer.append( new CKEDITOR.dom.text( '\u200b', doc ) );
+
+		// Inline widgets don't need a resizer wrapper as an image spans the entire widget.
+		if ( !widget.inline ) {
+			var imageOrLink = widget.parts.link || widget.parts.image,
+				oldResizeWrapper = imageOrLink.getParent(),
+				resizeWrapper = doc.createElement( 'span' );
+
+			resizeWrapper.addClass( 'cke_image_resizer_wrapper' );
+			resizeWrapper.append( imageOrLink );
+			resizeWrapper.append( resizer );
+			widget.element.append( resizeWrapper, true );
+
+			// Remove the old wrapper which could came from e.g. pasted HTML
+			// and which could be corrupted (e.g. resizer span has been lost).
+			if ( oldResizeWrapper.is( 'span' ) )
+				oldResizeWrapper.remove();
+		} else {
+			widget.wrapper.append( resizer );
+		}
+
+		// Calculate values of size variables and mouse offsets.
+		resizer.on( 'mousedown', function( evt ) {
+			var image = widget.parts.image,
+
+				// "factor" can be either 1 or -1. I.e.: For right-aligned images, we need to
+				// subtract the difference to get proper width, etc. Without "factor",
+				// resizer starts working the opposite way.
+				factor = widget.data.align == 'right' ? -1 : 1,
+
+				// The x-coordinate of the mouse relative to the screen
+				// when button gets pressed.
+				startX = evt.data.$.screenX,
+				startY = evt.data.$.screenY,
+
+				// The initial dimensions and aspect ratio of the image.
+				startWidth = image.$.clientWidth,
+				startHeight = image.$.clientHeight,
+				ratio = startWidth / startHeight,
+
+				listeners = [],
+
+				// A class applied to editable during resizing.
+				cursorClass = 'cke_image_s' + ( !~factor ? 'w' : 'e' ),
+
+				nativeEvt, newWidth, newHeight, updateData,
+				moveDiffX, moveDiffY, moveRatio;
+
+			// Save the undo snapshot first: before resizing.
+			editor.fire( 'saveSnapshot' );
+
+			// Mousemove listeners are removed on mouseup.
+			attachToDocuments( 'mousemove', onMouseMove, listeners );
+
+			// Clean up the mousemove listener. Update widget data if valid.
+			attachToDocuments( 'mouseup', onMouseUp, listeners );
+
+			// The entire editable will have the special cursor while resizing goes on.
+			editable.addClass( cursorClass );
+
+			// This is to always keep the resizer element visible while resizing.
+			resizer.addClass( 'cke_image_resizing' );
+
+			// Attaches an event to a global document if inline editor.
+			// Additionally, if classic (`iframe`-based) editor, also attaches the same event to `iframe`'s document.
+			function attachToDocuments( name, callback, collection ) {
+				var globalDoc = CKEDITOR.document,
+					listeners = [];
+
+				if ( !doc.equals( globalDoc ) )
+					listeners.push( globalDoc.on( name, callback ) );
+
+				listeners.push( doc.on( name, callback ) );
+
+				if ( collection ) {
+					for ( var i = listeners.length; i--; )
+						collection.push( listeners.pop() );
+				}
+			}
+
+			// Calculate with first, and then adjust height, preserving ratio.
+			function adjustToX() {
+				newWidth = startWidth + factor * moveDiffX;
+				newHeight = Math.round( newWidth / ratio );
+			}
+
+			// Calculate height first, and then adjust width, preserving ratio.
+			function adjustToY() {
+				newHeight = startHeight - moveDiffY;
+				newWidth = Math.round( newHeight * ratio );
+			}
+
+			// This is how variables refer to the geometry.
+			// Note: x corresponds to moveOffset, this is the position of mouse
+			// Note: o corresponds to [startX, startY].
+			//
+			// 	+--------------+--------------+
+			// 	|              |              |
+			// 	|      I       |      II      |
+			// 	|              |              |
+			// 	+------------- o -------------+ _ _ _
+			// 	|              |              |      ^
+			// 	|      VI      |     III      |      | moveDiffY
+			// 	|              |         x _ _ _ _ _ v
+			// 	+--------------+---------|----+
+			// 	               |         |
+			// 	                <------->
+			// 	                moveDiffX
+			function onMouseMove( evt ) {
+				nativeEvt = evt.data.$;
+
+				// This is how far the mouse is from the point the button was pressed.
+				moveDiffX = nativeEvt.screenX - startX;
+				moveDiffY = startY - nativeEvt.screenY;
+
+				// This is the aspect ratio of the move difference.
+				moveRatio = Math.abs( moveDiffX / moveDiffY );
+
+				// Left, center or none-aligned widget.
+				if ( factor == 1 ) {
+					if ( moveDiffX <= 0 ) {
+						// Case: IV.
+						if ( moveDiffY <= 0 )
+							adjustToX();
+
+						// Case: I.
+						else {
+							if ( moveRatio >= ratio )
+								adjustToX();
+							else
+								adjustToY();
+						}
+					} else {
+						// Case: III.
+						if ( moveDiffY <= 0 ) {
+							if ( moveRatio >= ratio )
+								adjustToY();
+							else
+								adjustToX();
+						}
+
+						// Case: II.
+						else {
+							adjustToY();
+						}
+					}
+				}
+
+				// Right-aligned widget. It mirrors behaviours, so I becomes II,
+				// IV becomes III and vice-versa.
+				else {
+					if ( moveDiffX <= 0 ) {
+						// Case: IV.
+						if ( moveDiffY <= 0 ) {
+							if ( moveRatio >= ratio )
+								adjustToY();
+							else
+								adjustToX();
+						}
+
+						// Case: I.
+						else {
+							adjustToY();
+						}
+					} else {
+						// Case: III.
+						if ( moveDiffY <= 0 )
+							adjustToX();
+
+						// Case: II.
+						else {
+							if ( moveRatio >= ratio ) {
+								adjustToX();
+							} else {
+								adjustToY();
+							}
+						}
+					}
+				}
+
+				// Don't update attributes if less than 10.
+				// This is to prevent images to visually disappear.
+				if ( newWidth >= 15 && newHeight >= 15 ) {
+					image.setAttributes( { width: newWidth, height: newHeight } );
+					updateData = true;
+				} else {
+					updateData = false;
+				}
+			}
+
+			function onMouseUp() {
+				var l;
+
+				while ( ( l = listeners.pop() ) )
+					l.removeListener();
+
+				// Restore default cursor by removing special class.
+				editable.removeClass( cursorClass );
+
+				// This is to bring back the regular behaviour of the resizer.
+				resizer.removeClass( 'cke_image_resizing' );
+
+				if ( updateData ) {
+					widget.setData( { width: newWidth, height: newHeight } );
+
+					// Save another undo snapshot: after resizing.
+					editor.fire( 'saveSnapshot' );
+				}
+
+				// Don't update data twice or more.
+				updateData = false;
+			}
+		} );
+
+		// Change the position of the widget resizer when data changes.
+		widget.on( 'data', function() {
+			resizer[ widget.data.align == 'right' ? 'addClass' : 'removeClass' ]( 'cke_image_resizer_left' );
+		} );
+	}
+
+	// Integrates widget alignment setting with justify
+	// plugin's commands (execution and refreshment).
+	// @param {CKEDITOR.editor} editor
+	// @param {String} value 'left', 'right', 'center' or 'block'
+	function alignCommandIntegrator( editor ) {
+		var execCallbacks = [],
+			enabled;
+
+		return function( value ) {
+			var command = editor.getCommand( 'justify' + value );
+
+			// Most likely, the justify plugin isn't loaded.
+			if ( !command )
+				return;
+
+			// This command will be manually refreshed along with
+			// other commands after exec.
+			execCallbacks.push( function() {
+				command.refresh( editor, editor.elementPath() );
+			} );
+
+			if ( value in { right: 1, left: 1, center: 1 } ) {
+				command.on( 'exec', function( evt ) {
+					var widget = getFocusedWidget( editor );
+
+					if ( widget ) {
+						widget.setData( 'align', value );
+
+						// Once the widget changed its align, all the align commands
+						// must be refreshed: the event is to be cancelled.
+						for ( var i = execCallbacks.length; i--; )
+							execCallbacks[ i ]();
+
+						evt.cancel();
+					}
+				} );
+			}
+
+			command.on( 'refresh', function( evt ) {
+				var widget = getFocusedWidget( editor ),
+					allowed = { right: 1, left: 1, center: 1 };
+
+				if ( !widget )
+					return;
+
+				// Cache "enabled" on first use. This is because filter#checkFeature may
+				// not be available during plugin's afterInit in the future — a moment when
+				// alignCommandIntegrator is called.
+				if ( enabled === undefined )
+					enabled = editor.filter.checkFeature( editor.widgets.registered.image.features.align );
+
+				// Don't allow justify commands when widget alignment is disabled (#11004).
+				if ( !enabled )
+					this.setState( CKEDITOR.TRISTATE_DISABLED );
+				else {
+					this.setState(
+						( widget.data.align == value ) ? (
+							CKEDITOR.TRISTATE_ON
+						) : (
+							( value in allowed ) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED
+						)
+					);
+				}
+
+				evt.cancel();
+			} );
+		};
+	}
+
+	function linkCommandIntegrator( editor ) {
+		// Nothing to integrate with if link is not loaded.
+		if ( !editor.plugins.link )
+			return;
+
+		CKEDITOR.on( 'dialogDefinition', function( evt ) {
+			var dialog = evt.data;
+
+			if ( dialog.name == 'link' ) {
+				var def = dialog.definition;
+
+				var onShow = def.onShow,
+					onOk = def.onOk;
+
+				def.onShow = function() {
+					var widget = getFocusedWidget( editor ),
+						displayTextField = this.getContentElement( 'info', 'linkDisplayText' ).getElement().getParent().getParent();
+
+					// Widget cannot be enclosed in a link, i.e.
+					//		<a>foo<inline widget/>bar</a>
+					if ( widget && ( widget.inline ? !widget.wrapper.getAscendant( 'a' ) : 1 ) ) {
+						this.setupContent( widget.data.link || {} );
+
+						// Hide the display text in case of linking image2_chamilo widget.
+						displayTextField.hide();
+					} else {
+						// Make sure that display text is visible, as it might be hidden by image2_chamilo integration
+						// before.
+						displayTextField.show();
+						onShow.apply( this, arguments );
+					}
+				};
+
+				// Set widget data if linking the widget using
+				// link dialog (instead of default action).
+				// State shifter handles data change and takes
+				// care of internal DOM structure of linked widget.
+				def.onOk = function() {
+					var widget = getFocusedWidget( editor );
+
+					// Widget cannot be enclosed in a link, i.e.
+					//		<a>foo<inline widget/>bar</a>
+					if ( widget && ( widget.inline ? !widget.wrapper.getAscendant( 'a' ) : 1 ) ) {
+						var data = {};
+
+						// Collect data from fields.
+						this.commitContent( data );
+
+						// Set collected data to widget.
+						widget.setData( 'link', data );
+					} else {
+						onOk.apply( this, arguments );
+					}
+				};
+			}
+		} );
+
+		// Overwrite default behaviour of unlink command.
+		editor.getCommand( 'unlink' ).on( 'exec', function( evt ) {
+			var widget = getFocusedWidget( editor );
+
+			// Override unlink only when link truly belongs to the widget.
+			// If wrapped inline widget in a link, let default unlink work (#11814).
+			if ( !widget || !widget.parts.link )
+				return;
+
+			widget.setData( 'link', null );
+
+			// Selection (which is fake) may not change if unlinked image in focused widget,
+			// i.e. if captioned image. Let's refresh command state manually here.
+			this.refresh( editor, editor.elementPath() );
+
+			evt.cancel();
+		} );
+
+		// Overwrite default refresh of unlink command.
+		editor.getCommand( 'unlink' ).on( 'refresh', function( evt ) {
+			var widget = getFocusedWidget( editor );
+
+			if ( !widget )
+				return;
+
+			// Note that widget may be wrapped in a link, which
+			// does not belong to that widget (#11814).
+			this.setState( widget.data.link || widget.wrapper.getAscendant( 'a' ) ?
+				CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED );
+
+			evt.cancel();
+		} );
+	}
+
+	// Returns the focused widget, if of the type specific for this plugin.
+	// If no widget is focused, `null` is returned.
+	//
+	// @param {CKEDITOR.editor}
+	// @returns {CKEDITOR.plugins.widget}
+	function getFocusedWidget( editor ) {
+		var widget = editor.widgets.focused;
+
+		if ( widget && widget.name == 'image' )
+			return widget;
+
+		return null;
+	}
+
+	// Returns a set of widget allowedContent rules, depending
+	// on configurations like config#image2_chamilo_alignClasses or
+	// config#image2_chamilo_captionedClass.
+	//
+	// @param {CKEDITOR.editor}
+	// @returns {Object}
+	function getWidgetAllowedContent( editor ) {
+		var alignClasses = editor.config.image2_chamilo_alignClasses,
+			rules = {
+				// Widget may need <div> or <p> centering wrapper.
+				div: {
+					match: centerWrapperChecker( editor )
+				},
+				p: {
+					match: centerWrapperChecker( editor )
+				},
+				img: {
+					attributes: '!src,alt,width,height'
+				},
+				figure: {
+					classes: '!' + editor.config.image2_chamilo_captionedClass
+				},
+				figcaption: true
+			};
+
+		if ( alignClasses ) {
+			// Centering class from the config.
+			rules.div.classes = alignClasses[ 1 ];
+			rules.p.classes = rules.div.classes;
+
+			// Left/right classes from the config.
+			rules.img.classes = alignClasses[ 0 ] + ',' + alignClasses[ 2 ];
+			rules.figure.classes += ',' + rules.img.classes;
+		} else {
+			// Centering with text-align.
+			rules.div.styles = 'text-align';
+			rules.p.styles = 'text-align';
+
+			rules.img.styles = 'float';
+			rules.figure.styles = 'float,display';
+		}
+
+		return rules;
+	}
+
+	// Returns a set of widget feature rules, depending
+	// on editor configuration. Note that the following may not cover
+	// all the possible cases since requiredContent supports a single
+	// tag only.
+	//
+	// @param {CKEDITOR.editor}
+	// @returns {Object}
+	function getWidgetFeatures( editor ) {
+		var alignClasses = editor.config.image2_chamilo_alignClasses,
+			features = {
+				dimension: {
+					requiredContent: 'img[width,height]'
+				},
+				align: {
+					requiredContent: 'img' +
+						( alignClasses ? '(' + alignClasses[ 0 ] + ')' : '{float}' )
+				},
+				caption: {
+					requiredContent: 'figcaption'
+				},
+				responsive: {
+					requiredContent: 'img'
+				}
+			};
+
+		return features;
+	}
+
+	// Returns element which is styled, considering current
+	// state of the widget.
+	//
+	// @see CKEDITOR.plugins.widget#applyStyle
+	// @param {CKEDITOR.plugins.widget} widget
+	// @returns {CKEDITOR.dom.element}
+	function getStyleableElement( widget ) {
+		return widget.data.hasCaption ? widget.element : widget.parts.image;
+	}
+} )();
+
+/**
+ * A CSS class applied to the `<figure>` element of a captioned image.
+ *
+ * Read more in the [documentation](#!/guide/dev_captionedimage) and see the
+ * [SDK sample](http://sdk.ckeditor.com/samples/captionedimage.html).
+ *
+ *		// Changes the class to "captionedImage".
+ *		config.image2_chamilo_captionedClass = 'captionedImage';
+ *
+ * @cfg {String} [image2_chamilo_captionedClass='image']
+ * @member CKEDITOR.config
+ */
+CKEDITOR.config.image2_chamilo_captionedClass = 'image';
+
+/**
+ * Determines whether dimension inputs should be automatically filled when the image URL changes in the Enhanced Image
+ * plugin dialog window.
+ *
+ * Read more in the [documentation](#!/guide/dev_captionedimage) and see the
+ * [SDK sample](http://sdk.ckeditor.com/samples/captionedimage.html).
+ *
+ *		config.image2_chamilo_prefillDimensions = false;
+ *
+ * @since 4.5
+ * @cfg {Boolean} [image2_chamilo_prefillDimensions=true]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Disables the image resizer. By default the resizer is enabled.
+ *
+ * Read more in the [documentation](#!/guide/dev_captionedimage) and see the
+ * [SDK sample](http://sdk.ckeditor.com/samples/captionedimage.html).
+ *
+ *		config.image2_chamilo_disableResizer = true;
+ *
+ * @since 4.5
+ * @cfg {Boolean} [image2_chamilo_disableResizer=false]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * CSS classes applied to aligned images. Useful to take control over the way
+ * the images are aligned, i.e. to customize output HTML and integrate external stylesheets.
+ *
+ * Classes should be defined in an array of three elements, containing left, center, and right
+ * alignment classes, respectively. For example:
+ *
+ *		config.image2_chamilo_alignClasses = [ 'align-left', 'align-center', 'align-right' ];
+ *
+ * **Note**: Once this configuration option is set, the plugin will no longer produce inline
+ * styles for alignment. It means that e.g. the following HTML will be produced:
+ *
+ *		<img alt="My image" class="custom-center-class" src="foo.png" />
+ *
+ * instead of:
+ *
+ *		<img alt="My image" style="float:left" src="foo.png" />
+ *
+ * **Note**: Once this configuration option is set, corresponding style definitions
+ * must be supplied to the editor:
+ *
+ * * For [classic editor](#!/guide/dev_framed) it can be done by defining additional
+ * styles in the {@link CKEDITOR.config#contentsCss stylesheets loaded by the editor}. The same
+ * styles must be provided on the target page where the content will be loaded.
+ * * For [inline editor](#!/guide/dev_inline) the styles can be defined directly
+ * with `<style> ... <style>` or `<link href="..." rel="stylesheet">`, i.e. within the `<head>`
+ * of the page.
+ *
+ * For example, considering the following configuration:
+ *
+ *		config.image2_chamilo_alignClasses = [ 'align-left', 'align-center', 'align-right' ];
+ *
+ * CSS rules can be defined as follows:
+ *
+ *		.align-left {
+ *			float: left;
+ *		}
+ *
+ *		.align-right {
+ *			float: right;
+ *		}
+ *
+ *		.align-center {
+ *			text-align: center;
+ *		}
+ *
+ *		.align-center > figure {
+ *			display: inline-block;
+ *		}
+ *
+ * Read more in the [documentation](#!/guide/dev_captionedimage) and see the
+ * [SDK sample](http://sdk.ckeditor.com/samples/captionedimage.html).
+ *
+ * @since 4.4
+ * @cfg {String[]} [image2_chamilo_alignClasses=null]
+ * @member CKEDITOR.config
+ */
+
+/**
+ * Determines whether alternative text is required for the captioned image.
+ *
+ *		config.image2_chamilo_altRequired = true;
+ *
+ * Read more in the [documentation](#!/guide/dev_captionedimage) and see the
+ * [SDK sample](http://sdk.ckeditor.com/samples/captionedimage.html).
+ *
+ * @since 4.6.0
+ * @cfg {Boolean} [image2_chamilo_altRequired=false]
+ * @member CKEDITOR.config
+ */