Improve SVG icon compatibility with RTL languages by adding the @rtl@ parameter to @sprite_icon@ method. When it is @true@, it adds the 'icon-rtl' class to SVG icons, flipping their direction if an RTL language is used (#42465).

git-svn-id: https://svn.redmine.org/redmine/trunk@23654 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Marius Balteanu
2025-04-13 20:30:19 +00:00
parent e85cd113fe
commit 6951e569c4
16 changed files with 34 additions and 29 deletions

View File

@@ -372,6 +372,10 @@ a.wiki-anchor {margin-left:0px; margin-right:6px;}
padding-left:0; padding-right:20px;
}
svg.icon-svg.icon-rtl {
transform: scaleX(-1);
}
div.issue img.gravatar {
float: right;
margin: 0 0 0 6px;

View File

@@ -21,10 +21,10 @@ module IconsHelper
DEFAULT_ICON_SIZE = "18"
DEFAULT_SPRITE = "icons"
def sprite_icon(icon_name, label = nil, icon_only: false, size: DEFAULT_ICON_SIZE, css_class: nil, sprite: DEFAULT_SPRITE, plugin: nil)
def sprite_icon(icon_name, label = nil, icon_only: false, size: DEFAULT_ICON_SIZE, css_class: nil, sprite: DEFAULT_SPRITE, plugin: nil, rtl: false)
sprite = plugin ? "plugin_assets/#{plugin}/#{sprite}.svg" : "#{sprite}.svg"
svg_icon = svg_sprite_icon(icon_name, size: size, css_class: css_class, sprite: sprite)
svg_icon = svg_sprite_icon(icon_name, size: size, css_class: css_class, sprite: sprite, rtl: rtl)
if label
label_classes = ["icon-label"]
@@ -92,9 +92,10 @@ module IconsHelper
private
def svg_sprite_icon(icon_name, size: DEFAULT_ICON_SIZE, sprite: DEFAULT_SPRITE, css_class: nil)
def svg_sprite_icon(icon_name, size: DEFAULT_ICON_SIZE, sprite: DEFAULT_SPRITE, css_class: nil, rtl: false)
css_classes = "s#{size} icon-svg"
css_classes += " #{css_class}" unless css_class.nil?
css_classes += " icon-rtl" if rtl
content_tag(
:svg,

View File

@@ -10,7 +10,7 @@
<div id="query_form_content">
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
<legend onclick="toggleFieldset(this);" class="icon icon-<%= @query.new_record? ? "expanded" : "collapsed" %>">
<%= sprite_icon(@query.new_record? ? "angle-down" : "angle-right") %>
<%= sprite_icon(@query.new_record? ? "angle-down" : "angle-right", rtl: !@query.new_record?) %>
<%= l(:label_filter_plural) %>
</legend>
<div style="<%= @query.new_record? ? "" : "display: none;" %>">

View File

@@ -12,7 +12,7 @@
<% if @allowed_statuses.present? %>
<li class="folder">
<a href="#" class="submenu"><%= l(:field_status) %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<% @allowed_statuses.each do |s| -%>
<li>
@@ -34,7 +34,7 @@
<% if @trackers.present? %>
<li class="folder">
<a href="#" class="submenu"><%= l(:field_tracker) %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<% @trackers.each do |t| -%>
<li><%= context_menu_link t.name, _bulk_update_issues_path(@issue, :ids => @issue_ids, :issue => {'tracker_id' => t}, :back_url => @back), :method => :patch,
@@ -47,7 +47,7 @@
<% if @safe_attributes.include?('priority_id') && @priorities.present? -%>
<li class="folder">
<a href="#" class="submenu"><%= l(:field_priority) %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<% @priorities.each do |p| -%>
<li><%= context_menu_link p.name, _bulk_update_issues_path(@issue, :ids => @issue_ids, :issue => {'priority_id' => p}, :back_url => @back), :method => :patch,
@@ -60,7 +60,7 @@
<% if @safe_attributes.include?('fixed_version_id') && @versions.present? -%>
<li class="folder">
<a href="#" class="submenu"><%= l(:field_fixed_version) %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<% @versions.sort.each do |v| -%>
<li><%= context_menu_link format_version_name(v), _bulk_update_issues_path(@issue, :ids => @issue_ids, :issue => {'fixed_version_id' => v}, :back_url => @back), :method => :patch,
@@ -75,7 +75,7 @@
<% if @safe_attributes.include?('assigned_to_id') && @assignables.present? -%>
<li class="folder">
<a href="#" class="submenu"><%= l(:field_assigned_to) %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<% if @assignables.include?(User.current) %>
<li><%= context_menu_link "<< #{l(:label_me)} >>", _bulk_update_issues_path(@issue, :ids => @issue_ids, :issue => {'assigned_to_id' => User.current}, :back_url => @back), :method => :patch,
@@ -94,7 +94,7 @@
<% if @safe_attributes.include?('category_id') && @project && @project.issue_categories.any? -%>
<li class="folder">
<a href="#" class="submenu"><%= l(:field_category) %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<% @project.issue_categories.each do |u| -%>
<li><%= context_menu_link u.name, _bulk_update_issues_path(@issue, :ids => @issue_ids, :issue => {'category_id' => u}, :back_url => @back), :method => :patch,
@@ -109,7 +109,7 @@
<% if @safe_attributes.include?('done_ratio') && Issue.use_field_for_done_ratio? %>
<li class="folder">
<a href="#" class="submenu"><%= l(:field_done_ratio) %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<% (0..10).map{|x|x*10}.each do |p| -%>
<li><%= context_menu_link "#{p}%", _bulk_update_issues_path(@issue, :ids => @issue_ids, :issue => {'done_ratio' => p}, :back_url => @back), :method => :patch,
@@ -122,7 +122,7 @@
<% @options_by_custom_field.each do |field, options| %>
<li class="folder <%= field.css_classes %>">
<a href="#" class="submenu"><%= field.name %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<% options.each do |text, value| %>
<li><%= bulk_update_custom_field_context_menu_link(field, text, value || text) %></li>
@@ -137,7 +137,7 @@
<% if @can[:add_watchers] %>
<li class="folder">
<a href="#" class="submenu"><%= l(:label_issue_watchers) %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<li><%= context_menu_link sprite_icon('add', l(:button_add)),
new_watchers_path(:object_type => 'issue', :object_id => @issue_ids),

View File

@@ -12,7 +12,7 @@
<% if @activities.present? -%>
<li class="folder">
<a href="#" class="submenu"><%= l(:field_activity) %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<% @activities.each do |u| -%>
<li><%= context_menu_link u.name, {:controller => 'timelog', :action => 'bulk_update', :ids => @time_entries.collect(&:id), :time_entry => {'activity_id' => u}, :back_url => @back}, :method => :post,
@@ -25,7 +25,7 @@
<% @options_by_custom_field.each do |field, options| %>
<li class="folder <%= field.css_classes %>">
<a href="#" class="submenu"><%= field.name %></a>
<span class="icon-only"><%= sprite_icon('angle-right') %></span>
<span class="icon-only"><%= sprite_icon('angle-right', rtl: true) %></span>
<ul>
<% options.each do |text, value| %>
<li><%= bulk_update_time_entry_custom_field_context_menu_link(field, text, value || text) %></li>

View File

@@ -16,7 +16,7 @@
<div id="query_form_content">
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
<legend onclick="toggleFieldset(this);" class="icon icon-<%= @query.new_record? ? "expanded" : "collapsed" %>">
<%= sprite_icon(@query.new_record? ? "angle-down" : "angle-right") %>
<%= sprite_icon(@query.new_record? ? "angle-down" : "angle-right", rtl: !@query.new_record?) %>
<%= l(:label_filter_plural) %>
</legend>
<div style="<%= @query.new_record? ? "" : "display: none;" %>">
@@ -26,7 +26,7 @@
<fieldset id="options" class="collapsible collapsed">
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed">
<%= sprite_icon("angle-right") %>
<%= sprite_icon("angle-right", rtl: true) %>
<%= l(:label_options) %>
</legend>
<div style="display: none;">

View File

@@ -7,7 +7,7 @@
<fieldset class="box tabular collapsible collapsed">
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed">
<%= sprite_icon("angle-right") %>
<%= sprite_icon("angle-right", rtl: true) %>
<%= l(:label_relations_mapping) %>
</legend>
<div id="relations-mapping" style="display: none;">

View File

@@ -106,7 +106,7 @@
<% if sidebar_content? %>
<div id="sidebar-switch-panel" style="visibility: hidden;">
<a id="sidebar-switch-button" class="" href="#">
<%= sprite_icon("chevrons-right", size: 20) %></a>
<%= sprite_icon("chevrons-right", size: 20, rtl: true) %></a>
</div>
<%= javascript_tag "$('#sidebar-switch-panel').css('visibility', 'visible');" %>
<% end %>

View File

@@ -6,7 +6,7 @@
<div id="query_form_content">
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
<legend onclick="toggleFieldset(this);" class="icon icon-<%= @query.new_record? ? "expanded" : "collapsed" %>">
<%= sprite_icon(@query.new_record? ? "angle-down" : "angle-right") %>
<%= sprite_icon(@query.new_record? ? "angle-down" : "angle-right", rtl: !@query.new_record?) %>
<%= l(:label_filter_plural) %>
</legend>
<div style="<%= @query.new_record? ? "" : "display: none;" %>">
@@ -17,7 +17,7 @@
<% if @query.available_columns.any? %>
<fieldset id="options" class="collapsible collapsed">
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed">
<%= sprite_icon("angle-right") %>
<%= sprite_icon("angle-right", rtl: true) %>
<%= l(:label_options) %>
</legend>
<div class="hidden">

View File

@@ -14,7 +14,7 @@
:path => to_path_param(ent_path),
:rev => @rev,
:depth => (depth + 1),
:parent_id => tr_id)) %>');"><%= sprite_icon('angle-right') %></span>
:parent_id => tr_id)) %>');"><%= sprite_icon('angle-right', rtl: true) %></span>
<% end %>
<%= link_to file_icon(entry, ent_name),
{:action => (entry.is_dir? ? 'show' : 'entry'), :id => @project, :repository_id => @repository.identifier_param, :path => to_path_param(ent_path), :rev => @rev},

View File

@@ -3,7 +3,7 @@
<div class="hide-when-print">
<fieldset id="filters" class="collapsible collapsed">
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed">
<%= sprite_icon("angle-right") %>
<%= sprite_icon("angle-right", rtl: true) %>
<%= l(:label_filter_plural) %>
</legend>
<div style="display: none;">

View File

@@ -25,7 +25,7 @@
<fieldset class="collapsible collapsed">
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed">
<%= sprite_icon("angle-right") %>
<%= sprite_icon("angle-right", rtl: true) %>
<%= l(:label_options) %>
</legend>
<div id="options-content" style="display:none;">

View File

@@ -42,7 +42,7 @@
</ul>
<% if @completed_versions.present? %>
<p>
<%= link_to_function sprite_icon('angle-right', l(:label_completed_versions)),
<%= link_to_function sprite_icon('angle-right', l(:label_completed_versions), rtl: true),
'$("#toggle-completed-versions").toggleClass("icon-collapsed icon-expanded"); $("#completed-versions").toggle(); toggleExpendCollapseIcon(this);',
:id => 'toggle-completed-versions', :class => 'icon icon-collapsed collapsible' %>
<ul id = "completed-versions" style = "display:none;">

View File

@@ -63,7 +63,7 @@
<fieldset class="collapsible collapsed hide-when-print">
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed">
<%= sprite_icon("angle-right") %>
<%= sprite_icon("angle-right", rtl: true) %>
<%= l(:label_attachment_plural) %> (<%= @page.attachments.length %>)
</legend>
<div style="display: none;">

View File

@@ -41,7 +41,7 @@
<fieldset class="collapsible" style="padding: 0; margin-top: 0.5em;">
<legend onclick="toggleFieldset(this);" class="icon icon-<%= @workflows['author'].present? ? "expanded" : "collapsed" %>">
<%= sprite_icon(@workflows['author'].present? ? "angle-down" : "angle-right") %>
<%= sprite_icon(@workflows['author'].present? ? "angle-down" : "angle-right", rtl: !@workflows['author'].present?) %>
<%= l(:label_additional_workflow_transitions_for_author) %>
</legend>
<div id="author_workflows" style="margin: 0.5em 0 0.5em 0;">
@@ -52,7 +52,7 @@
<fieldset class="collapsible" style="padding: 0;">
<legend onclick="toggleFieldset(this);" class="icon icon-<%= @workflows['assignee'].present? ? "expanded" : "collapsed" %>">
<%= sprite_icon(@workflows['assignee'].present? ? "angle-down" : "angle-right") %>
<%= sprite_icon(@workflows['assignee'].present? ? "angle-down" : "angle-right", rtl: !@workflows['assignee'].present?) %>
<%= l(:label_additional_workflow_transitions_for_assignee) %>
</legend>
<div id="assignee_workflows" style="margin: 0.5em 0 0.5em 0;">

View File

@@ -248,7 +248,7 @@ module Redmine
hide_label = args[1] || args[0] || l(:button_hide)
js = "$('##{html_id}-show, ##{html_id}-hide').toggle(); $('##{html_id}').fadeToggle(150);"
out = ''.html_safe
out << link_to_function(sprite_icon('angle-right', show_label), js, :id => "#{html_id}-show", :class => 'icon icon-collapsed collapsible')
out << link_to_function(sprite_icon('angle-right', show_label, rtl: true), js, :id => "#{html_id}-show", :class => 'icon icon-collapsed collapsible')
out <<
link_to_function(
sprite_icon('angle-down', hide_label), js,