Skip to content

Commit

Permalink
Merge pull request #13255 from ckeditor/ck/5820
Browse files Browse the repository at this point in the history
Feature (special-characters): The name of special character categories can be translatable. Closes #5820.
  • Loading branch information
psmyrek authored Jan 13, 2023
2 parents 2c60308 + 52457f0 commit 1616fc9
Show file tree
Hide file tree
Showing 18 changed files with 191 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function SpecialCharactersEmoji( editor ) {
{ title: 'wind blowing face', character: '🌬️' },
{ title: 'floppy disk', character: '💾' },
{ title: 'heart', character: '❤️' }
] );
], { label: 'Emoticons' } );
}

ClassicEditor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function SpecialCharactersEmoji( editor ) {
{ title: 'wind blowing face', character: '🌬️' },
{ title: 'floppy disk', character: '💾' },
{ title: 'heart', character: '❤️' }
] );
], { label: 'Emoticons' } );
}

ClassicEditor
Expand All @@ -66,6 +66,10 @@ After adding the above plugin to the editor configuration, the new category will
The title of a special character must be unique across the entire special characters set.
</info-box>

<info-box>
The third argument of the {@link module:special-characters/specialcharacters~SpecialCharacters#addItems `SpecialCharacters#addItems()`} method is optional. You can use it to specify a label displayed as a category name. It is useful when your editor uses a language other than English. Check out the {@link features/ui-language UI language guide} to learn more.
</info-box>

Below you can see a demo based on the example shown above. Use the special characters icon in the editor toolbar and then select "Emoji" in the select dropdown in order to insert an emoji into the WYSIWYG editor.

{@snippet features/special-characters-new-category}
Expand Down
6 changes: 6 additions & 0 deletions packages/ckeditor5-special-characters/lang/contexts.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
{
"Special characters": "Name of the special characters plugins, visible in a dropdown and as a button tooltip.",
"All": "A category name is displayed in a special characters dropdown representing all available symbols.",
"Arrows": "A category name is displayed in a special characters dropdown representing arrow symbols.",
"Currency": "A category name is displayed in a special characters dropdown representing currency symbols.",
"Latin": "A category name is displayed in a special characters dropdown representing latin symbols.",
"Mathematical": "A category name is displayed in a special characters dropdown representing mathematical symbols.",
"Text": "A category name is displayed in a special characters dropdown representing text symbols.",
"leftwards simple arrow": "A label for the \"leftwards simple arrow\" symbol.",
"rightwards simple arrow": "A label for the \"rightwards simple arrow\" symbol.",
"upwards simple arrow": "A label for the \"upwards simple arrow\" symbol.",
Expand Down
48 changes: 36 additions & 12 deletions packages/ckeditor5-special-characters/src/specialcharacters.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export default class SpecialCharacters extends Plugin {
constructor( editor ) {
super( editor );

const t = editor.t;

/**
* Registered characters. A pair of a character name and its symbol.
*
Expand All @@ -58,12 +60,20 @@ export default class SpecialCharacters extends Plugin {
this._characters = new Map();

/**
* Registered groups. Each group contains a collection with symbol names.
* Registered groups. Each group contains a displayed label and a collection with symbol names.
*
* @private
* @member {Map.<String, Set.<String>>} #_groups
* @member {Map.<String, {items: Set.<String>, label: String}>} #_groups
*/
this._groups = new Map();

/**
* A label describing the "All" special characters category.
*
* @private
* @member {String} #_allSpecialCharactersGroupLabel
*/
this._allSpecialCharactersGroupLabel = t( 'All' );
}

/**
Expand Down Expand Up @@ -126,22 +136,24 @@ export default class SpecialCharacters extends Plugin {
*
* @param {String} groupName
* @param {Array.<module:special-characters/specialcharacters~SpecialCharacterDefinition>} items
* @param {Object} options
* @param {String} [options.label=groupName]
*/
addItems( groupName, items ) {
addItems( groupName, items, options = { label: groupName } ) {
if ( groupName === ALL_SPECIAL_CHARACTERS_GROUP ) {
/**
* The name "All" for a special category group cannot be used because it is a special category that displays all
* available special characters.
*
* @error special-character-invalid-group-name
*/
throw new CKEditorError( 'special-character-invalid-group-name', null, { ALL_SPECIAL_CHARACTERS_GROUP } );
throw new CKEditorError( 'special-character-invalid-group-name', null );
}

const group = this._getGroup( groupName );
const group = this._getGroup( groupName, options.label );

for ( const item of items ) {
group.add( item.title );
group.items.add( item.title );
this._characters.set( item.title, item.character );
}
}
Expand Down Expand Up @@ -183,7 +195,11 @@ export default class SpecialCharacters extends Plugin {
return new Set( this._characters.keys() );
}

return this._groups.get( groupName );
const group = this._groups.get( groupName );

if ( group ) {
return group.items;
}
}

/**
Expand All @@ -202,10 +218,14 @@ export default class SpecialCharacters extends Plugin {
*
* @private
* @param {String} groupName The name of the group to create.
* @param {String} label The label describing the new group.
*/
_getGroup( groupName ) {
_getGroup( groupName, label ) {
if ( !this._groups.has( groupName ) ) {
this._groups.set( groupName, new Set() );
this._groups.set( groupName, {
items: new Set(),
label
} );
}

return this._groups.get( groupName );
Expand Down Expand Up @@ -240,10 +260,14 @@ export default class SpecialCharacters extends Plugin {
* @returns {Object} Returns an object with `navigationView`, `gridView` and `infoView` properties, containing UI parts.
*/
_createDropdownPanelContent( locale, dropdownView ) {
const specialCharsGroups = Array.from( this.getGroups() );
// The map contains a name of category (an identifier) and its label (a translational string).
const specialCharsGroups = new Map( [
// Add a special group that shows all available special characters.
[ ALL_SPECIAL_CHARACTERS_GROUP, this._allSpecialCharactersGroupLabel ],

// Add a special group that shows all available special characters.
specialCharsGroups.unshift( ALL_SPECIAL_CHARACTERS_GROUP );
...Array.from( this.getGroups() )
.map( name => ( [ name, this._groups.get( name ).label ] ) )
] );

const navigationView = new SpecialCharactersNavigationView( locale, specialCharsGroups );
const gridView = new CharacterGridView( locale );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ export default class SpecialCharactersArrows extends Plugin {
{ title: t( 'on with exclamation mark with left right arrow above' ), character: '🔛' },
{ title: t( 'soon with rightwards arrow above' ), character: '🔜' },
{ title: t( 'top with upwards arrow above' ), character: '🔝' }
] );
], { label: t( 'Arrows' ) } );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,6 @@ export default class SpecialCharactersCurrency extends Plugin {
{ character: '₻', title: t( 'Nordic mark sign' ) },
{ character: '₼', title: t( 'Manat sign' ) },
{ character: '₽', title: t( 'Ruble sign' ) }
] );
], { label: t( 'Currency' ) } );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,6 @@ export default class SpecialCharactersLatin extends Plugin {
{ character: 'Ž', title: t( 'Latin capital letter z with caron' ) },
{ character: 'ž', title: t( 'Latin small letter z with caron' ) },
{ character: 'ſ', title: t( 'Latin small letter long s' ) }
] );
], { label: t( 'Latin' ) } );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,6 @@ export default class SpecialCharactersMathematical extends Plugin {
{ character: '¼', title: t( 'Vulgar fraction one quarter' ) },
{ character: '½', title: t( 'Vulgar fraction one half' ) },
{ character: '¾', title: t( 'Vulgar fraction three quarters' ) }
] );
], { label: t( 'Mathematical' ) } );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,6 @@ export default class SpecialCharactersText extends Plugin {
{ character: '§', title: t( 'Section sign' ) },
{ character: '¶', title: t( 'Paragraph sign' ) },
{ character: '⁋', title: t( 'Reversed paragraph sign' ) }
] );
], { label: t( 'Text' ) } );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default class SpecialCharactersNavigationView extends FormHeaderView {
* class.
*
* @param {module:utils/locale~Locale} locale The localization services instance.
* @param {Iterable.<String>} groupNames The names of the character groups.
* @param {Map.<String, String>} groupNames The names of the character groups and their displayed labels.
*/
constructor( locale, groupNames ) {
super( locale );
Expand Down Expand Up @@ -70,7 +70,7 @@ export default class SpecialCharactersNavigationView extends FormHeaderView {
* Returns a dropdown that allows selecting character groups.
*
* @private
* @param {Iterable.<String>} groupNames The names of the character groups.
* @param {Map.<String, String>} groupNames The names of the character groups and their displayed labels.
* @returns {module:ui/dropdown/dropdownview~DropdownView}
*/
_createGroupDropdown( groupNames ) {
Expand All @@ -79,9 +79,9 @@ export default class SpecialCharactersNavigationView extends FormHeaderView {
const dropdown = createDropdown( locale );
const groupDefinitions = this._getCharacterGroupListItemDefinitions( dropdown, groupNames );

dropdown.set( 'value', groupDefinitions.first.model.label );
dropdown.set( 'value', groupDefinitions.first.model.name );

dropdown.buttonView.bind( 'label' ).to( dropdown, 'value' );
dropdown.buttonView.bind( 'label' ).to( dropdown, 'value', value => groupNames.get( value ) );

dropdown.buttonView.set( {
isOn: false,
Expand All @@ -91,7 +91,7 @@ export default class SpecialCharactersNavigationView extends FormHeaderView {
} );

dropdown.on( 'execute', evt => {
dropdown.value = evt.source.label;
dropdown.value = evt.source.name;
} );

dropdown.delegate( 'execute' ).to( this );
Expand All @@ -107,23 +107,24 @@ export default class SpecialCharactersNavigationView extends FormHeaderView {
*
* @private
* @param {module:ui/dropdown/dropdownview~DropdownView} dropdown
* @param {Iterable.<String>} groupNames The names of the character groups.
* @param {Map.<String, String>} groupNames The names of the character groups and their displayed labels.
* @returns {Iterable.<module:ui/dropdown/utils~ListDropdownItemDefinition>}
*/
_getCharacterGroupListItemDefinitions( dropdown, groupNames ) {
const groupDefs = new Collection();

for ( const name of groupNames ) {
for ( const [ name, label ] of groupNames ) {
const definition = {
type: 'button',
model: new Model( {
label: name,
name,
label,
withText: true
} )
};

definition.model.bind( 'isOn' ).to( dropdown, 'value', value => {
return value === definition.model.label;
return value === definition.model.name;
} );

groupDefs.add( definition );
Expand Down
19 changes: 18 additions & 1 deletion packages/ckeditor5-special-characters/tests/specialcharacters.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ describe( 'SpecialCharacters', () => {
const navigation = dropdown.panelView.children.first.navigationView;

expect( grid.tiles.get( 0 ).label ).to.equal( '<' );
navigation.groupDropdownView.fire( new EventInfo( { label: 'Arrows' }, 'execute' ) );
navigation.groupDropdownView.fire( new EventInfo( { name: 'Arrows' }, 'execute' ) );

expect( grid.tiles.get( 0 ).label ).to.equal( '←' );
} );
Expand Down Expand Up @@ -244,6 +244,23 @@ describe( 'SpecialCharacters', () => {
expect( plugin._characters.size ).to.equal( startingCharacterSize + 2 );
} );

it( 'allows defining a displayed label different from a category name', () => {
plugin.addItems( 'Symbols', [
{ title: 'arrow left', character: '←' },
{ title: 'arrow right', character: '→' }
], { label: 'Custom arrows plugin' } );

expect( plugin._groups.has( 'Symbols' ) ).to.equal( true );

const arrowGroup = plugin._groups.get( 'Symbols' );

expect( arrowGroup ).to.have.property( 'label', 'Custom arrows plugin' );
expect( arrowGroup ).to.have.property( 'items' );
expect( arrowGroup.items.size ).to.equal( 2 );
expect( arrowGroup.items.has( 'arrow left' ) ).to.equal( true );
expect( arrowGroup.items.has( 'arrow right' ) ).to.equal( true );
} );

it( 'does not accept "All" as a group name', () => {
expectToThrowCKEditorError( () => {
plugin.addItems( 'All', [] );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,16 @@ describe( 'SpecialCharactersArrows', () => {
expect( addItemsFirstCallArgs[ 0 ] ).to.equal( 'Arrows' );
} );

it( 'defines a label displayed in the toolbar', () => {
expect( addItemsFirstCallArgs[ 2 ] ).to.deep.equal( {
label: 'Arrows'
} );
} );

it( 'adds proper characters', () => {
expect( addItemsFirstCallArgs[ 1 ] ).to.deep.include( {
title: 'rightwards double arrow',
character: ''
title: 'leftwards arrow to bar',
character: ''
} );

expect( addItemsFirstCallArgs[ 1 ] ).to.deep.include( {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ describe( 'SpecialCharactersCurrency', () => {
expect( addItemsFirstCallArgs[ 0 ] ).to.equal( 'Currency' );
} );

it( 'defines a label displayed in the toolbar', () => {
expect( addItemsFirstCallArgs[ 2 ] ).to.deep.equal( {
label: 'Currency'
} );
} );

it( 'adds proper characters', () => {
expect( addItemsFirstCallArgs[ 1 ] ).to.deep.include( {
character: '¢',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ describe( 'SpecialCharactersLatin', () => {
expect( addItemsFirstCallArgs[ 0 ] ).to.equal( 'Latin' );
} );

it( 'defines a label displayed in the toolbar', () => {
expect( addItemsFirstCallArgs[ 2 ] ).to.deep.equal( {
label: 'Latin'
} );
} );

it( 'adds proper characters', () => {
expect( addItemsFirstCallArgs[ 1 ] ).to.deep.include( {
character: 'Ō',
Expand Down
Loading

0 comments on commit 1616fc9

Please sign in to comment.