Feature #13839 » custom_field_layout_editing.diff
| app/helpers/projects_helper.rb | ||
|---|---|---|
| 22 | 22 |
tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural},
|
| 23 | 23 |
{:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural},
|
| 24 | 24 |
{:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural},
|
| 25 |
{:name => 'custom_fields_layouts', :action => :manage_custom_fields_layout, :partial => 'projects/settings/custom_fields_layout', :label => :label_custom_field_plural},
|
|
| 25 | 26 |
{:name => 'versions', :action => :manage_versions, :partial => 'projects/settings/versions', :label => :label_version_plural},
|
| 26 | 27 |
{:name => 'categories', :action => :manage_categories, :partial => 'projects/settings/issue_categories', :label => :label_issue_category_plural},
|
| 27 | 28 |
{:name => 'resolutions', :action => :manage_resolutions, :partial => 'projects/settings/issue_resolutions', :label => :label_issue_resolution_plural},
|
| app/helpers/custom_fields_helper.rb | ||
|---|---|---|
| 85 | 85 | |
| 86 | 86 |
content_tag "label", content + |
| 87 | 87 |
(required ? " <span class=\"required\">*</span>".html_safe : ""), |
| 88 |
:for => "#{name}_custom_field_values_#{custom_value.custom_field.id}"
|
|
| 88 |
:for => "#{name}_custom_field_values_#{custom_value.custom_field.id}", :class => "custom_field_label"
|
|
| 89 | 89 |
end |
| 90 | 90 | |
| 91 | 91 |
# Return custom field tag with its label tag |
| app/models/custom_field_layout.rb | ||
|---|---|---|
| 1 |
class CustomFieldLayout < ActiveRecord::Base |
|
| 2 |
|
|
| 3 |
end |
|
| app/controllers/custom_fields_layouts_controller.rb | ||
|---|---|---|
| 1 |
class CustomFieldsLayoutsController < ApplicationController |
|
| 2 |
helper :all |
|
| 3 |
before_filter :find_custom_field_values |
|
| 4 | ||
| 5 |
def new |
|
| 6 |
@layout = CustomFieldLayout.new(project_id: @project.id, tracker_id: @tracker.id) |
|
| 7 |
end |
|
| 8 |
|
|
| 9 |
def apply |
|
| 10 |
if @cf_layout.nil? |
|
| 11 |
@layout = CustomFieldLayout.new(project_id: @project.id, tracker_id: @tracker.id) |
|
| 12 |
@layout.location = JSON.parse(params[:ids]) |
|
| 13 |
@layout.project_id = @project.id |
|
| 14 |
@layout.tracker_id = @tracker.id |
|
| 15 |
if @layout.save |
|
| 16 |
redirect_to settings_project_path(@project) |
|
| 17 |
end |
|
| 18 |
else |
|
| 19 |
@cf_layout.location = JSON.parse(params[:ids]) |
|
| 20 |
if @cf_layout.save |
|
| 21 |
redirect_to settings_project_path(@project) |
|
| 22 |
end |
|
| 23 |
end |
|
| 24 |
end |
|
| 25 | ||
| 26 |
def show |
|
| 27 |
respond_to do |format| |
|
| 28 |
format.js |
|
| 29 |
end |
|
| 30 |
end |
|
| 31 |
|
|
| 32 |
private |
|
| 33 |
def find_custom_field_values |
|
| 34 |
@project = Project.find(params[:project_id]) |
|
| 35 |
@tracker = Tracker.find(params[:layout][:tracker_id]) |
|
| 36 |
|
|
| 37 |
#get last edited custom field location |
|
| 38 |
@cf_layout = CustomFieldLayout.find_by({:tracker_id => @tracker.id, :project_id => @project.id})
|
|
| 39 |
cf_ids = @cf_layout.nil? ? [[],[]] : JSON.parse(@cf_layout.location.gsub("nil","null"))
|
|
| 40 |
|
|
| 41 |
#get ids of nil elements |
|
| 42 |
ids_of_nil = [[],[]] |
|
| 43 |
cf_ids.each_index{ |i| cf_ids[i].each_index.select{|k| ids_of_nil[i] << k if cf_ids[i][k].nil?}}.map!{|i| i -= [nil]}
|
|
| 44 |
|
|
| 45 |
#get default custom field location |
|
| 46 |
default_values = (@project.issues.new(:tracker_id => @tracker.id, |
|
| 47 |
:subject => " ", :author_id => @current_user).editable_custom_field_values) |
|
| 48 | ||
| 49 |
#if not set yet then default |
|
| 50 |
if !cf_ids.all?{|array| array.empty?}
|
|
| 51 |
ordered_values = default_values.group_by(&:custom_field_id).values_at(*cf_ids.flatten).flatten(1) |
|
| 52 |
added = default_values - ordered_values |
|
| 53 |
@custom_fields_values = [ordered_values[0 ... cf_ids.first.count], |
|
| 54 |
ordered_values[cf_ids.first.count .. -1] + added] |
|
| 55 |
ids_of_nil.each_index{|i| ids_of_nil[i].each{|v| @custom_fields_values[i].insert(v,nil)}}
|
|
| 56 |
else |
|
| 57 |
@custom_fields_values = [default_values[0 ... default_values.count/2], default_values[default_values.count/2 .. -1]] |
|
| 58 |
end |
|
| 59 |
end |
|
| 60 |
end |
|
| app/controllers/projects_controller.rb | ||
|---|---|---|
| 161 | 161 |
@member ||= @project.members.new |
| 162 | 162 |
@trackers = Tracker.sorted.to_a |
| 163 | 163 |
@wiki ||= @project.wiki || Wiki.new(:project => @project) |
| 164 |
@layout = CustomFieldLayout.new() |
|
| 165 |
|
|
| 164 | 166 |
end |
| 165 | 167 | |
| 166 | 168 |
def edit |
| app/views/custom_fields_layouts/show.js.erb | ||
|---|---|---|
| 1 |
$("#cfv").html('<%= escape_javascript(render(partial: "show"))%>');
|
|
| 2 | ||
| app/views/custom_fields_layouts/_custom_fields_layout.html.erb | ||
|---|---|---|
| 1 |
<div class="splitcontent"> |
|
| 2 |
<div class="splitcontentleft"> |
|
| 3 |
<div class="sortable"> |
|
| 4 |
<% i = 0 %> |
|
| 5 |
<% custom_fields_values.each do |side|%> |
|
| 6 |
<% side.each do |value|%> |
|
| 7 |
<% if !value.nil? %> |
|
| 8 |
<p class="custom_field_p" id=<%=value.custom_field_id%>> |
|
| 9 |
<%= custom_field_tag_with_label :issue, value, :required => issue.required_attribute?(value.custom_field_id) %> |
|
| 10 |
</p> |
|
| 11 |
<%else %> |
|
| 12 |
<p class="custom_field_p clean"%></p> |
|
| 13 |
<% end %> |
|
| 14 |
<% end -%> |
|
| 15 |
<% i = i + 1 %> |
|
| 16 |
<% if (i == 1) %> |
|
| 17 |
</div></div> <div class="splitcontentright"> <div class="sortable"> |
|
| 18 |
<% end -%> |
|
| 19 |
<% end -%> |
|
| 20 |
</div> |
|
| 21 |
<p> </p> |
|
| 22 |
</div> |
|
| 23 |
</div> |
|
| 24 | ||
| app/views/custom_fields_layouts/_show.html.erb | ||
|---|---|---|
| 1 |
<% issue = @project.issues.new(tracker_id: @tracker.id, subject: " ", author_id: @current_user) %> |
|
| 2 | ||
| 3 |
<%= render partial: "custom_fields_layout" , locals: {issue: issue, custom_fields_values: @custom_fields_values} %>
|
|
| 4 | ||
| 5 | ||
| app/views/projects/settings/_custom_fields_layout.html.erb | ||
|---|---|---|
| 1 |
<h2><%= l(:label_custom_field_layout) %></h2> |
|
| 2 |
<script> |
|
| 3 | ||
| 4 |
function addBlank(){
|
|
| 5 |
$(".splitcontent").children().find(".sortable").each(
|
|
| 6 |
function(){
|
|
| 7 |
var cf_count = $(this).children().length; |
|
| 8 |
if (cf_count == 0){ $(this).append("<p class='custom_field_p clean'> </p>") };
|
|
| 9 |
}); |
|
| 10 | ||
| 11 |
} |
|
| 12 | ||
| 13 |
/*add sortable ui to added elements*/ |
|
| 14 |
function loadCf(){
|
|
| 15 |
if($('.custom_field_label').length != 0) {
|
|
| 16 |
|
|
| 17 |
/*add fields for removing/adding if there is smth to add/remove */ |
|
| 18 |
$(".add_remove").append(" <p class='custom_field_remove' > <%= l(:label_remove_field) %> </p>");
|
|
| 19 |
$(".copy").append("<p class='custom_field_p clean'> <%= l(:label_move_field) %> </p> ");
|
|
| 20 | ||
| 21 |
/*add blank div by default if any splitcontent is fully empty |
|
| 22 |
to show where we can move element*/ |
|
| 23 |
addBlank(); |
|
| 24 |
|
|
| 25 |
/*make borders of divs visible*/ |
|
| 26 |
$(".custom_field_p, .custom_field_remove").css({"border" : "thin solid",
|
|
| 27 |
"border-color" : "#ddd"}); |
|
| 28 |
$(".custom_field_remove").css({"border-color" : "#B00"});
|
|
| 29 |
$(".custom_field_p.clean").css({"height" : "2.3em"});
|
|
| 30 |
$(".sortable").css({"min-height": "4.6em",
|
|
| 31 |
"border-style" : "ridge", |
|
| 32 |
"padding" : "4px", |
|
| 33 |
"border-width": "1px", |
|
| 34 |
"border-color" : "#dddFFF"}); |
|
| 35 | ||
| 36 | ||
| 37 |
/*make elements sortable (allow reordering)*/ |
|
| 38 |
/*not allow moving last elements in the splitcontent(left|right) */ |
|
| 39 |
var is_alone = 1; |
|
| 40 |
$(".sortable").sortable({connectWith: ".sortable",
|
|
| 41 |
dropOnEmpty: true, |
|
| 42 |
receive: function(e,ui) {
|
|
| 43 |
copyHelper= null;} |
|
| 44 |
}); |
|
| 45 | ||
| 46 |
/*allow to copy blank div and make it sortable*/ |
|
| 47 |
$( ".copy" ).sortable({
|
|
| 48 |
connectWith: ".sortable", |
|
| 49 |
forcePlaceholderSize: false, |
|
| 50 |
helper: function(e,li) {
|
|
| 51 |
copyHelper= li.clone().insertAfter(li.text(""));
|
|
| 52 |
return li.clone(); |
|
| 53 |
}, |
|
| 54 |
stop: function() {
|
|
| 55 |
copyHelper && copyHelper.remove(); |
|
| 56 |
} |
|
| 57 |
}); |
|
| 58 | ||
| 59 |
/* make field droppable (moving div inside droppable one removes it)*/ |
|
| 60 |
$('.custom_field_remove').droppable({
|
|
| 61 |
accept: ".clean", |
|
| 62 |
drop: function(event, ui) { ui.draggable.remove(); }
|
|
| 63 |
}); |
|
| 64 |
|
|
| 65 |
}}; |
|
| 66 | ||
| 67 |
/*get custom fields for selected tracker*/ |
|
| 68 |
function getCustomFields() {
|
|
| 69 |
$(".clean").remove();
|
|
| 70 |
$(".custom_field_remove").remove();
|
|
| 71 |
var tracker = $("#layout_tracker_id").find(":selected").val();
|
|
| 72 |
$.ajax({
|
|
| 73 |
method: "get", |
|
| 74 |
url: "<%= url_for :controller=>'custom_fields_layouts', :action => 'show', :project_id => @project %>", |
|
| 75 |
contentType: 'application/json', |
|
| 76 |
data: {layout: { tracker_id: tracker}},
|
|
| 77 |
cache: false, |
|
| 78 |
error: function(jqXHR, textStatus, errorThrown){
|
|
| 79 |
alert('Exception' + errorThrown);
|
|
| 80 |
}, |
|
| 81 |
success: function(){ loadCf(); }
|
|
| 82 |
}) |
|
| 83 |
}; |
|
| 84 | ||
| 85 |
/*get custom fields after loading*/ |
|
| 86 |
$(document).ready(function(){
|
|
| 87 |
getCustomFields(); |
|
| 88 |
}); |
|
| 89 | ||
| 90 | ||
| 91 | ||
| 92 |
/*set custom field ids on hidden field */ |
|
| 93 |
function setCfIds(){
|
|
| 94 |
var array = []; |
|
| 95 |
var left = []; |
|
| 96 |
var right = []; |
|
| 97 |
$("#cfv").find(".splitcontentleft").find(".custom_field_p").each(function() {
|
|
| 98 |
left.push(parseInt($(this).attr("id")));
|
|
| 99 |
}); |
|
| 100 |
$("#cfv").find(".splitcontentright").find(".custom_field_p").each(function() {
|
|
| 101 |
right.push(parseInt($(this).attr("id")));
|
|
| 102 |
}); |
|
| 103 |
array.push(left,right); |
|
| 104 |
$("#custom_fields_locations").val(JSON.stringify(array));
|
|
| 105 |
} ; |
|
| 106 | ||
| 107 |
/* don't need datepicker functionality for editing locations of custom fields*/ |
|
| 108 | ||
| 109 | ||
| 110 | ||
| 111 |
</script> |
|
| 112 | ||
| 113 |
<div class="box tabular"> |
|
| 114 | ||
| 115 |
<%= labelled_form_for @layout,:as => 'layout', url: {controller: "custom_fields_layouts",
|
|
| 116 |
action: "apply", :project_id => @project} do |f| %> |
|
| 117 | ||
| 118 |
<% include_calendar_headers_tags %> |
|
| 119 |
<% if @project.issues.new.safe_attribute? 'tracker_id' %> |
|
| 120 |
<p><%= f.select :tracker_id, @project.trackers.collect {|t| [t.name, t.id]}, {:required => true},
|
|
| 121 |
:onchange => "getCustomFields();" %></p> |
|
| 122 |
<%end%> |
|
| 123 |
|
|
| 124 |
<div class= "add_remove"> </div><p > </p> |
|
| 125 |
|
|
| 126 |
<div id="cfv"> </div> |
|
| 127 | ||
| 128 |
<%= hidden_field_tag :ids, "", :id => "custom_fields_locations" %> |
|
| 129 |
<%= submit_tag l(:button_update), :onclick => "setCfIds();" %> |
|
| 130 |
|
|
| 131 |
<div class ="splitcontentright copy"> </div> |
|
| 132 | ||
| 133 |
<%end %> |
|
| 134 |
</div> |
|
| app/views/issues/show.html.erb | ||
|---|---|---|
| 72 | 72 |
rows.right l(:label_spent_time), (@issue.total_spent_hours > 0 ? link_to(l_hours(@issue.total_spent_hours), issue_time_entries_path(@issue)) : "-"), :class => 'spent-time' |
| 73 | 73 |
end |
| 74 | 74 |
end %> |
| 75 | ||
| 76 | ||
| 75 | 77 |
<%= render_custom_fields_rows(@issue) %> |
| 76 | 78 |
<%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %> |
| 77 | 79 |
</table> |
| 80 | ||
| 81 | ||
| lib/redmine.rb | ||
|---|---|---|
| 86 | 86 |
map.permission :manage_members, {:projects => :settings, :members => [:index, :show, :new, :create, :update, :destroy, :autocomplete]}, :require => :member
|
| 87 | 87 |
map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
|
| 88 | 88 |
map.permission :add_subprojects, {:projects => [:new, :create]}, :require => :member
|
| 89 | ||
| 89 |
map.permission :manage_custom_fields_layout, {:projects => :settings, :custom_fields_editing => [:apply]}, :require => :member
|
|
| 90 |
|
|
| 90 | 91 |
map.project_module :issue_tracking do |map| |
| 91 | 92 |
# Issues |
| 92 | 93 |
map.permission :view_issues, {:issues => [:index, :show],
|
| app/views/issues/_form_custom_fields.html.erb | ||
|---|---|---|
| 1 |
<% custom_field_values = @issue.editable_custom_field_values %> |
|
| 2 |
<% if custom_field_values.present? %> |
|
| 3 |
<div class="splitcontent"> |
|
| 4 |
<div class="splitcontentleft"> |
|
| 5 |
<% i = 0 %> |
|
| 6 |
<% split_on = (custom_field_values.size / 2.0).ceil - 1 %> |
|
| 7 |
<% custom_field_values.each do |value| %> |
|
| 8 |
<p><%= custom_field_tag_with_label :issue, value, :required => @issue.required_attribute?(value.custom_field_id) %></p> |
|
| 9 |
<% if i == split_on -%> |
|
| 10 |
</div><div class="splitcontentright"> |
|
| 11 |
<% end -%> |
|
| 12 |
<% i += 1 -%> |
|
| 13 |
<% end -%> |
|
| 14 |
</div> |
|
| 15 |
</div> |
|
| 16 |
<% end %> |
|
| 1 |
<% cf_layout = CustomFieldLayout.all.where(:tracker_id => @issue.tracker_id, :project_id => @project.id).last %> |
|
| 2 |
<% default_values = @issue.editable_custom_field_values %> |
|
| 3 |
<% cf_ids = cf_layout.nil? ? [[],[]] : JSON.parse(cf_layout.location.gsub("nil","null")) %>
|
|
| 4 |
|
|
| 5 |
<% ids_of_nil = [[],[]] %> |
|
| 6 |
<% cf_ids.each_index{ |i| cf_ids[i].each_index.select{|k| ids_of_nil[i] << k if cf_ids[i][k].nil?}}.map!{|i| i -= [nil]} %>
|
|
| 7 | ||
| 8 |
<% if !cf_ids.all?{|array| array.empty?} %>
|
|
| 9 |
<% ordered_values = default_values.group_by(&:custom_field_id).values_at(*cf_ids.flatten).flatten(1) %> |
|
| 10 |
<% added = default_values - ordered_values %> |
|
| 11 |
<% custom_fields_values = [ordered_values[0 ... cf_ids.first.count], |
|
| 12 |
ordered_values[cf_ids.first.count .. -1] + added] %> |
|
| 13 |
<% ids_of_nil.each_index{|i| ids_of_nil[i].each{|v| custom_fields_values[i].insert(v,nil)}} %>
|
|
| 14 |
<% else %> |
|
| 15 |
<% custom_fields_values = [default_values[0 ... default_values.count/2], default_values[default_values.count/2 .. -1]] %> |
|
| 16 |
<% end %> |
|
| 17 | ||
| 18 |
<%= render partial: "custom_fields_layouts/custom_fields_layout" , locals: {issue: @issue, custom_fields_values: custom_fields_values} %>
|
|
| 19 | ||
| 20 | ||
| config/routes.rb | ||
|---|---|---|
| 136 | 136 |
get 'versions.:format', :to => 'versions#index' |
| 137 | 137 |
get 'roadmap', :to => 'versions#index', :format => false |
| 138 | 138 |
get 'versions', :to => 'versions#index' |
| 139 |
|
|
| 140 |
resources :custom_fields_layouts, :only => [:show] |
|
| 141 |
match 'settings/custom_fields_layouts', :to => 'custom_fields_layouts#apply', :via => [:post] |
|
| 139 | 142 | |
| 140 | 143 |
resources :news, :except => [:show, :edit, :update, :destroy] |
| 141 | 144 |
resources :time_entries, :controller => 'timelog', :except => [:show, :edit, :update, :destroy] do |
| app/helpers/issues_helper.rb | ||
|---|---|---|
| 220 | 220 |
r.to_html |
| 221 | 221 |
end |
| 222 | 222 | |
| 223 |
#add empty elements for proper cfs showing |
|
| 224 |
def add_nills(cfs) |
|
| 225 |
diff = cfs[0].count - cfs[1].count |
|
| 226 |
if (diff > 0) |
|
| 227 |
cfs[1] += [nil] * diff |
|
| 228 |
elsif (diff < 0) |
|
| 229 |
cfs[0] += [nil] * (-diff) |
|
| 230 |
end |
|
| 231 |
cfs |
|
| 232 |
end |
|
| 233 | ||
| 223 | 234 |
def render_custom_fields_rows(issue) |
| 224 |
values = issue.visible_custom_field_values |
|
| 225 |
return if values.empty? |
|
| 226 |
half = (values.size / 2.0).ceil |
|
| 227 |
issue_fields_rows do |rows| |
|
| 228 |
values.each_with_index do |value, i| |
|
| 229 |
css = "cf_#{value.custom_field.id}"
|
|
| 230 |
m = (i < half ? :left : :right) |
|
| 231 |
rows.send m, custom_field_name_tag(value.custom_field), show_value(value), :class => css |
|
| 235 |
default_values = issue.visible_custom_field_values |
|
| 236 |
return if default_values.empty? |
|
| 237 | ||
| 238 |
#get last edited custom field location |
|
| 239 |
cf_layout = CustomFieldLayout.find_by(:tracker_id => issue.tracker_id, :project_id => issue.project_id) |
|
| 240 |
cf_ids = cf_layout.nil? ? [[],[]] : JSON.parse(cf_layout.location.gsub("nil","null"))
|
|
| 241 | ||
| 242 |
#get ids of nil elements |
|
| 243 |
ids_of_nil = [[],[]] |
|
| 244 |
cf_ids.each_index{ |i| cf_ids[i].each_index.select{|k| ids_of_nil[i] << k if cf_ids[i][k].nil?}}.map!{|i| i -= [nil]}
|
|
| 245 | ||
| 246 |
#if not set yet then default |
|
| 247 |
if !cf_ids.all?{|array| array.empty?}
|
|
| 248 |
ordered_values = default_values.group_by(&:custom_field_id).values_at(*cf_ids.flatten).flatten(1) |
|
| 249 |
added = default_values - ordered_values |
|
| 250 |
custom_fields_values = [ordered_values[0 ... cf_ids.first.count], |
|
| 251 |
ordered_values[cf_ids.first.count .. -1] + added] |
|
| 252 |
ids_of_nil.each_index{|i| ids_of_nil[i].each{|v| custom_fields_values[i].insert(v,nil)}}
|
|
| 253 |
else |
|
| 254 |
custom_fields_values = [default_values[0 ... default_values.count/2], default_values[default_values.count/2 .. -1]] |
|
| 255 |
end |
|
| 256 |
custom_fields_values = add_nills(custom_fields_values) |
|
| 257 |
cfs = custom_fields_values[0].zip(custom_fields_values[1]).flatten |
|
| 258 | ||
| 259 |
s = "<tr>\n" |
|
| 260 |
n = 0 |
|
| 261 |
cfs.each do |value| |
|
| 262 |
s << "</tr>\n<tr>\n" if n > 0 && (n % 2) == 0 |
|
| 263 |
if value.nil? |
|
| 264 |
css = "custom_field_p clean" |
|
| 265 |
s << "\t<th class=\"#{css}\"> </th><td class=\"#{css}\"> </td>\n"
|
|
| 266 |
else |
|
| 267 |
css = "cf_#{value.custom_field_id}"
|
|
| 268 |
s << "\t<th class=\"#{css}\">#{ h(value.custom_field.name) }:</th><td class=\"#{css}\">#{ h(show_value(value)) }</td>\n"
|
|
| 232 | 269 |
end |
| 270 |
n +=1 |
|
| 233 | 271 |
end |
| 272 |
s << "</tr>\n" |
|
| 273 |
s.html_safe |
|
| 234 | 274 |
end |
| 235 | 275 |
# Returns the path for updating the issue form |
| config/locales/ru.yml | ||
|---|---|---|
| 469 | 469 |
label_current_version: Текущая версия |
| 470 | 470 |
label_custom_field: Настраиваемое поле |
| 471 | 471 |
label_custom_field_new: Новое настраиваемое поле |
| 472 |
label_custom_field_layout: Редактирование расположения кастомных полей |
|
| 472 | 473 |
label_custom_field_plural: Настраиваемые поля |
| 473 | 474 |
label_date_from: С |
| 474 | 475 |
label_date_from_to: С %{start} по %{end}
|
| ... | ... | |
| 577 | 578 |
label_month: Месяц |
| 578 | 579 |
label_more_than_ago: более, чем дней(я) назад |
| 579 | 580 |
label_more: Больше |
| 581 |
label_move_field: Переместите пустое поле |
|
| 580 | 582 |
label_my_account: Моя учётная запись |
| 581 | 583 |
label_my_page: Моя страница |
| 582 | 584 |
label_my_page_block: Блок моей страницы |
| ... | ... | |
| 625 | 627 |
label_project_plural2: проекта |
| 626 | 628 |
label_project_plural5: проектов |
| 627 | 629 |
label_public_projects: Общие проекты |
| 630 |
label_remove_field: Удалите пустое поле, перреместив его сюда |
|
| 628 | 631 |
label_query: Сохранённый запрос |
| 629 | 632 |
label_query_new: Новый запрос |
| 630 | 633 |
label_query_plural: Сохранённые запросы |
| config/locales/en.yml (revision 1956) | ||
|---|---|---|
| 551 | 551 |
label_custom_field: Custom field |
| 552 | 552 |
label_custom_field_plural: Custom fields |
| 553 | 553 |
label_custom_field_new: New custom field |
| 554 |
label_custom_field_layout: Edit custom fields layout |
|
| 554 | 555 |
label_enumerations: Enumerations |
| 555 | 556 |
label_enumeration_new: New value |
| 556 | 557 |
label_information: Information |
| ... | ... | |
| 560 | 561 |
label_login_with_open_id_option: or login with OpenID |
| 561 | 562 |
label_password_lost: Lost password |
| 562 | 563 |
label_home: Home |
| 564 |
label_move_field: Move blank field |
|
| 563 | 565 |
label_my_page: My page |
| 564 | 566 |
label_my_account: My account |
| 565 | 567 |
label_my_projects: My projects |
| ... | ... | |
| 572 | 574 |
label_assigned_to_me_issues: Issues assigned to me |
| 573 | 575 |
label_last_login: Last connection |
| 574 | 576 |
label_registered_on: Registered on |
| 577 |
label_remove_field: Remove blank fields moving them here |
|
| 575 | 578 |
label_activity: Activity |
| 576 | 579 |
label_overall_activity: Overall activity |
| 577 | 580 |
label_user_activity: "%{value}'s activity"
|
- « Previous
- 1
- 2
- 3
- 4
- Next »