blacklight-spotlight 3.0.0.alpha.10 → 3.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spotlight/admin/crop.es6 +6 -0
  3. data/app/assets/javascripts/spotlight/admin/sir-trevor/block_controls.js +21 -12
  4. data/app/assets/stylesheets/spotlight/_featured_browse_categories_block.scss +4 -4
  5. data/app/assets/stylesheets/spotlight/_item_text_block.scss +6 -0
  6. data/app/assets/stylesheets/spotlight/_report_a_problem.scss +5 -2
  7. data/app/controllers/spotlight/resources/csv_upload_controller.rb +1 -1
  8. data/app/jobs/spotlight/add_uploads_from_csv.rb +30 -5
  9. data/app/mailers/spotlight/indexing_complete_mailer.rb +3 -2
  10. data/app/models/spotlight/contact.rb +1 -1
  11. data/app/models/spotlight/custom_field.rb +3 -3
  12. data/app/models/spotlight/featured_image.rb +1 -1
  13. data/app/models/spotlight/page_configurations.rb +1 -0
  14. data/app/models/spotlight/page_content.rb +2 -0
  15. data/app/models/spotlight/resources/csv_upload.rb +2 -1
  16. data/app/models/spotlight/resources/iiif_manifest.rb +2 -0
  17. data/app/services/spotlight/solr_document_builder.rb +1 -0
  18. data/app/values/custom_field_name.rb +1 -0
  19. data/app/views/spotlight/indexing_complete_mailer/documents_indexed.html.erb +9 -0
  20. data/app/views/spotlight/pages/_form.html.erb +1 -1
  21. data/app/views/spotlight/shared/_honeypot_field.html.erb +4 -0
  22. data/app/views/spotlight/shared/_report_a_problem.html.erb +7 -10
  23. data/config/i18n-tasks.yml +2 -0
  24. data/config/locales/spotlight.ar.yml +22 -18
  25. data/config/locales/spotlight.en.yml +13 -6
  26. data/lib/generators/spotlight/install_generator.rb +22 -1
  27. data/lib/generators/spotlight/templates/config/initializers/sir_trevor_rails.rb +10 -0
  28. data/lib/generators/spotlight/templates/config/initializers/spotlight_initializer.rb +2 -0
  29. data/lib/spotlight/engine.rb +3 -0
  30. data/lib/spotlight/upload_field_config.rb +1 -0
  31. data/lib/spotlight/version.rb +1 -1
  32. data/spec/controllers/spotlight/browse_controller_spec.rb +1 -1
  33. data/spec/controllers/spotlight/resources/csv_upload_controller_spec.rb +4 -4
  34. data/spec/examples.txt +1410 -125
  35. data/spec/features/add_contacts_spec.rb +1 -1
  36. data/spec/features/browse_category_admin_spec.rb +2 -2
  37. data/spec/features/create_exhibit_spec.rb +5 -4
  38. data/spec/features/dashboard_spec.rb +5 -5
  39. data/spec/features/exhibits/administration_spec.rb +3 -3
  40. data/spec/features/exhibits/language_create_edit_spec.rb +3 -3
  41. data/spec/features/javascript/block_controls_spec.rb +2 -0
  42. data/spec/features/report_a_problem_spec.rb +5 -4
  43. data/spec/helpers/spotlight/pages_helper_spec.rb +2 -2
  44. data/spec/jobs/spotlight/add_uploads_from_csv_spec.rb +13 -1
  45. data/spec/mailers/spotlight/indexing_complete_mailer_spec.rb +11 -1
  46. data/spec/models/solr_document_spec.rb +2 -3
  47. data/spec/models/spotlight/access_controls_enforcement_search_builder_spec.rb +1 -0
  48. data/spec/models/spotlight/featured_image_spec.rb +0 -1
  49. data/spec/models/spotlight/role_spec.rb +2 -2
  50. data/spec/services/spotlight/exhibit_import_export_service_spec.rb +14 -2
  51. data/spec/services/spotlight/iiif_resource_resolver_spec.rb +1 -1
  52. data/spec/test_app_templates/Gemfile.extra +0 -3
  53. data/spec/views/spotlight/metadata_configurations/_metadata_field.html.erb_spec.rb +3 -3
  54. data/spec/views/spotlight/search_configurations/_sort.html.erb_spec.rb +7 -8
  55. data/vendor/assets/javascripts/leaflet-iiif.js +46 -21
  56. metadata +54 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27efff1c809c87463bcd240ccc65b6edca2182b73238f1027bc178a2f009ab5e
4
- data.tar.gz: 9df0f469fa0bc43f39a718d2cdb3bc7909e25da15a2e1d189ccc054b006eb579
3
+ metadata.gz: 8a3577af6f5ec30554f2e91955c7613e6501ef8e95f2822f6a92022626c03230
4
+ data.tar.gz: e45881b0867cba47bb74a93a7a008a843154383939c8db3abbb0c244e0a6ff57
5
5
  SHA512:
6
- metadata.gz: fc49fe51f1c599c5c3569d4387f7b2c1e124e9d8369a2b554ec26e441d8197f4f7e154cec7ab0b9c8fd3bdb8597315675da6d54b129df4774cdafbecfa339c9f
7
- data.tar.gz: c06bc5cd170cf772c13bf220bb8e0ebb136b81fb7a575b6cbfe16704fe77c4cf42c759131f9fda803361b909537ba97e9e366e58f4ab99b68d4275408b3c7853
6
+ metadata.gz: 7164e6ebcca3edd4db9d2b95ed7fafb2ec55188de3e16bdf92963b893e6b717dae262a7a2ab5f3fbfbe2e2f8de7a602083e2586b338fdbf5f1f2f96c4f5cb402
7
+ data.tar.gz: aaf1d73d51efd42699f32e1c9315ee43c4ab5e9bdb85e737eddbd94b4d9cf565e93deb58751074fecc5aaf8461cd82eb68db52fa5189db88df38035125e7ee60
@@ -40,6 +40,12 @@ export default class Crop {
40
40
  this.renderCropperMap();
41
41
 
42
42
  if (this.imageLayer) {
43
+ // Force a broken layer's container to be an element before removing.
44
+ // Code in leaflet-iiif land calls delete on the image layer's container when removing,
45
+ // which errors if there is an issue fetching the info.json and stops further necessary steps to execute.
46
+ if(!this.imageLayer._container) {
47
+ this.imageLayer._container = $('<div></div>');
48
+ }
43
49
  this.cropperMap.removeLayer(this.imageLayer);
44
50
  }
45
51
 
@@ -40,19 +40,28 @@
40
40
  }
41
41
  }
42
42
 
43
- return Object.keys(groups).reduce(function(memo, groupKey) {
44
- var group = groups[groupKey];
45
- var groupEl = $("<div class='st-controls-group'><div class='st-group-col-form-label'>" + groupKey + "</div></div>");
43
+ function generateBlock(groups, key) {
44
+ var group = groups[key];
45
+ var groupEl = $("<div class='st-controls-group'><div class='st-group-col-form-label'>" + key + "</div></div>");
46
46
  var buttons = group.reduce(function(memo, btn) {
47
47
  return memo += btn;
48
48
  }, "");
49
49
  groupEl.append(buttons);
50
- if (memo.length === 0) {
51
- return memo += groupEl[0].outerHTML;
52
- } else {
53
- return memo += "<hr />" + groupEl[0].outerHTML;
50
+ return groupEl[0].outerHTML;
51
+ }
52
+
53
+ var standardWidgets = generateBlock(groups, i18n.t("blocks:group:undefined"));
54
+
55
+ var exhibitWidgets = Object.keys(groups).map(function(key) {
56
+ if (key !== i18n.t("blocks:group:undefined")) {
57
+ return generateBlock(groups, key);
54
58
  }
55
- }, "");
59
+ }).filter(function (element) {
60
+ return element != null;
61
+ });
62
+
63
+ var blocks = [standardWidgets].concat(exhibitWidgets).join("<hr />");
64
+ return blocks;
56
65
  }
57
66
 
58
67
  function render(Blocks, availableTypes) {
@@ -65,7 +74,7 @@
65
74
  elButtons.appendChild(el);
66
75
  return elButtons;
67
76
  }
68
-
77
+
69
78
  global.Spotlight.BlockControls = function() { };
70
79
  global.Spotlight.BlockControls.create = function(editor) {
71
80
  // REFACTOR - should probably not know about blockManager
@@ -83,10 +92,10 @@
83
92
  SirTrevor = null;
84
93
  el = null;
85
94
  }
86
-
95
+
87
96
  function insert(e) {
88
97
  e.stopPropagation();
89
-
98
+
90
99
  var parent = this.parentNode;
91
100
  if (!parent || hide() === parent) { return; }
92
101
  $('.st-block__inner', parent).after(el);
@@ -101,7 +110,7 @@
101
110
 
102
111
  $(editor.wrapper).delegate(".st-block-replacer", "click", insert);
103
112
  $(editor.wrapper).delegate(".st-block-controls__button", "click", insert);
104
-
113
+
105
114
  return {
106
115
  el: el,
107
116
  hide: hide,
@@ -77,7 +77,7 @@ $aspect-ratio-factor-medium-image: 1; // 1:1 width: height
77
77
  width: $no-sidebar-desktop-large-image-width;
78
78
  height: $no-sidebar-desktop-large-image-width * $aspect-ratio-factor-large-image;
79
79
  }
80
- @media (min-width: breakpoint-min("xl")) {
80
+ @media (min-width: breakpoint-min("lg")) {
81
81
  width: $no-sidebar-large-desktop-large-image-width;
82
82
  height: $no-sidebar-large-desktop-large-image-width * $aspect-ratio-factor-large-image;
83
83
  }
@@ -111,11 +111,11 @@ $aspect-ratio-factor-medium-image: 1; // 1:1 width: height
111
111
  width: $with-sidebar-tablet-large-image-width;
112
112
  height: $with-sidebar-tablet-large-image-width * $aspect-ratio-factor-large-image;
113
113
  }
114
- @media (min-width: breakpoint-min("md")) and (max-width: breakpoint-max("xl")) {
114
+ @media (min-width: breakpoint-min("md")) and (max-width: breakpoint-max("lg")) {
115
115
  width: $with-sidebar-desktop-large-image-width;
116
116
  height: $with-sidebar-desktop-large-image-width * $aspect-ratio-factor-large-image;
117
117
  }
118
- @media (min-width: breakpoint-min("xl")) {
118
+ @media (min-width: breakpoint-min("lg")) {
119
119
  width: $with-sidebar-large-desktop-large-image-width;
120
120
  height: $with-sidebar-large-desktop-large-image-width * $aspect-ratio-factor-large-image;
121
121
  }
@@ -129,7 +129,7 @@ $aspect-ratio-factor-medium-image: 1; // 1:1 width: height
129
129
  width: $with-sidebar-xs-image-width;
130
130
  height: $with-sidebar-xs-image-width * $aspect-ratio-factor-medium-image;
131
131
  }
132
- @media (min-width: breakpoint-min("xl")) {
132
+ @media (min-width: breakpoint-min("lg")) {
133
133
  width: $with-sidebar-large-desktop-medium-image-width;
134
134
  height: $with-sidebar-large-desktop-medium-image-width * $aspect-ratio-factor-medium-image;
135
135
  }
@@ -21,6 +21,12 @@
21
21
  }
22
22
  }
23
23
 
24
+ .item-text {
25
+ .item-col {
26
+ z-index: 1;
27
+ }
28
+ }
29
+
24
30
  .item-text-admin {
25
31
  .text-align {
26
32
  margin-top: 15px;
@@ -1,7 +1,10 @@
1
1
  #report-problem-form {
2
2
  display: none;
3
- background-color: #e7e7e7;
4
- border-bottom: 1px dotted $gray-600;
3
+ border-bottom: 1px solid $gray-600;
4
+
5
+ h2 {
6
+ @extend .sr-only;
7
+ }
5
8
  }
6
9
 
7
10
  @include media-breakpoint-up(sm) {
@@ -16,7 +16,7 @@ module Spotlight
16
16
 
17
17
  def create
18
18
  csv = CSV.parse(csv_io_param, headers: true, return_headers: false).map(&:to_hash)
19
- Spotlight::AddUploadsFromCSV.perform_later(csv, current_exhibit, current_user)
19
+ Spotlight::AddUploadsFromCsv.perform_later(csv, current_exhibit, current_user)
20
20
  flash[:notice] = t('spotlight.resources.upload.csv.success', file_name: csv_io_name)
21
21
  redirect_to spotlight.admin_exhibit_catalog_path(current_exhibit)
22
22
  end
@@ -3,15 +3,41 @@
3
3
  module Spotlight
4
4
  ##
5
5
  # Process a CSV upload into new Spotlight::Resource::Upload objects
6
- class AddUploadsFromCSV < ActiveJob::Base
6
+ class AddUploadsFromCsv < ActiveJob::Base
7
+ attr_reader :count
8
+ attr_reader :errors
9
+
7
10
  queue_as :default
8
11
 
9
12
  after_perform do |job|
10
13
  csv_data, exhibit, user = job.arguments
11
- Spotlight::IndexingCompleteMailer.documents_indexed(csv_data, exhibit, user).deliver_now
14
+ Spotlight::IndexingCompleteMailer.documents_indexed(
15
+ csv_data,
16
+ exhibit,
17
+ user,
18
+ indexed_count: job.count,
19
+ errors: job.errors
20
+ ).deliver_now
12
21
  end
13
22
 
14
23
  def perform(csv_data, exhibit, _user)
24
+ @count = 0
25
+ @errors = {}
26
+
27
+ resources(csv_data, exhibit).each_with_index do |resource, index|
28
+ if resource.save_and_index
29
+ @count += 1
30
+ else
31
+ @errors[index + 1] = resource.errors.full_messages + resource.upload&.errors&.full_messages
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def resources(csv_data, exhibit)
39
+ return to_enum(:resources, csv_data, exhibit) unless block_given?
40
+
15
41
  encoded_csv(csv_data).each do |row|
16
42
  url = row.delete('url')
17
43
  next unless url.present?
@@ -21,12 +47,11 @@ module Spotlight
21
47
  exhibit: exhibit
22
48
  )
23
49
  resource.build_upload(remote_image_url: url) unless url == '~'
24
- resource.save_and_index
50
+
51
+ yield resource
25
52
  end
26
53
  end
27
54
 
28
- private
29
-
30
55
  def encoded_csv(csv)
31
56
  csv.map do |row|
32
57
  row.map do |label, column|
@@ -5,9 +5,10 @@ module Spotlight
5
5
  # Notify the curator that we're finished processing a
6
6
  # batch upload
7
7
  class IndexingCompleteMailer < ActionMailer::Base
8
- def documents_indexed(csv_data, exhibit, user)
9
- @number = csv_data.length
8
+ def documents_indexed(csv_data, exhibit, user, indexed_count: nil, errors: [])
9
+ @number = indexed_count || csv_data.length
10
10
  @exhibit = exhibit
11
+ @errors = errors
11
12
  mail(to: user.email, subject: 'Document indexing complete')
12
13
  end
13
14
  end
@@ -19,7 +19,7 @@ module Spotlight
19
19
  self.contact_info = contact_info.symbolize_keys
20
20
  end
21
21
 
22
- before_save on: :create do
22
+ before_create do
23
23
  self.show_in_sidebar = true if show_in_sidebar.nil?
24
24
  end
25
25
 
@@ -18,10 +18,10 @@ module Spotlight
18
18
  self.field_type ||= 'text'
19
19
  end
20
20
 
21
- before_save :update_field_name, on: :update, if: -> { field_type_changed? || readonly_field_changed? }
21
+ before_update :update_field_name, if: -> { field_type_changed? || readonly_field_changed? }
22
22
 
23
- after_commit :update_blacklight_configuration_after_field_name_change, on: :update, if: -> { saved_change_to_field? || saved_change_to_slug? }
24
- after_commit :update_sidecar_data_after_field_name_change, on: :update, if: -> { saved_change_to_field? || saved_change_to_slug? }
23
+ after_update_commit :update_blacklight_configuration_after_field_name_change, if: -> { saved_change_to_field? || saved_change_to_slug? }
24
+ after_update_commit :update_sidecar_data_after_field_name_change, if: -> { saved_change_to_field? || saved_change_to_slug? }
25
25
 
26
26
  def label=(label)
27
27
  configuration['label'] = label
@@ -66,7 +66,7 @@ module Spotlight
66
66
  def iiif_tilesource
67
67
  if self[:iiif_tilesource]
68
68
  self[:iiif_tilesource]
69
- elsif source == 'remote' && file_present?
69
+ elsif file_present?
70
70
  riiif = Riiif::Engine.routes.url_helpers
71
71
  riiif.info_path(id)
72
72
  end
@@ -27,6 +27,7 @@ module Spotlight
27
27
  to: :context
28
28
 
29
29
  attr_reader :context, :page
30
+
30
31
  def initialize(context:, page:)
31
32
  @context = context
32
33
  @page = page
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'spotlight/page_content/sir_trevor'
4
+
3
5
  module Spotlight
4
6
  # Factory for picking the right page content renderer
5
7
  module PageContent
@@ -3,9 +3,10 @@
3
3
  module Spotlight
4
4
  module Resources
5
5
  ##
6
- # Shim object for CSV Uploads. see {Spotlight::AddUploadsFromCSV}
6
+ # Shim object for CSV Uploads. see {Spotlight::AddUploadsFromCsv}
7
7
  class CsvUpload
8
8
  attr_reader :url
9
+
9
10
  include ActiveModel::Model
10
11
  extend ActiveModel::Translation
11
12
  end
@@ -6,6 +6,7 @@ module Spotlight
6
6
  # A PORO to construct a solr hash for a given IiifManifest
7
7
  class IiifManifest
8
8
  attr_reader :collection
9
+
9
10
  def initialize(attrs = {})
10
11
  @url = attrs[:url]
11
12
  @manifest = attrs[:manifest]
@@ -36,6 +37,7 @@ module Spotlight
36
37
  private
37
38
 
38
39
  attr_reader :url, :manifest, :exhibit, :solr_hash
40
+
39
41
  delegate :blacklight_config, to: :exhibit
40
42
 
41
43
  def add_document_id
@@ -8,6 +8,7 @@ module Spotlight
8
8
  end
9
9
 
10
10
  attr_reader :resource
11
+
11
12
  delegate :exhibit, :document_model, to: :resource
12
13
 
13
14
  ##
@@ -5,6 +5,7 @@
5
5
  class CustomFieldName
6
6
  delegate :readonly_field?, :configuration, :field_type, to: :custom_field
7
7
  attr_reader :custom_field
8
+
8
9
  def initialize(custom_field)
9
10
  @custom_field = custom_field
10
11
  end
@@ -1,3 +1,12 @@
1
1
  <p><%= t :".title" %></p>
2
2
 
3
3
  <p><%= t :".body", count: @number, title: @exhibit.title %></p>
4
+
5
+ <% if @errors.length > 0 %>
6
+ <p><%= t :".errors", default: :'spotlight.catalog.reindex_progress_panel.error' %></p>
7
+ <ul>
8
+ <% @errors.each do |index, message| %>
9
+ <li><%= t :'.error', index: index, message: message.to_sentence %>
10
+ <% end %>
11
+ </ul>
12
+ <% end %>
@@ -40,7 +40,7 @@
40
40
  </div>
41
41
  <div class="form-group">
42
42
  <%= f.label :content, class: 'sr-only' %>
43
- <%= f.text_area_without_bootstrap :content, value: { data: f.object.content.as_json }.to_json, class: content_editor_class(f.object), data: { 'block-types': Spotlight::Engine.config.sir_trevor_widgets } %>
43
+ <%= f.text_area_without_bootstrap :content, value: { data: f.object.content.as_json }.to_json, class: content_editor_class(f.object), data: { 'block-types': SirTrevorRails::Block.custom_block_types } %>
44
44
  </div>
45
45
  </div>
46
46
 
@@ -0,0 +1,4 @@
1
+ <span style="display:none;visibility:hidden;">
2
+ <% honeypot_field_name = Spotlight::Engine.config.spambot_honeypot_email_field %>
3
+ <%= f.email_field honeypot_field_name, label: t(:'spotlight.shared.report_a_problem.honeypot_field_explanation') %>
4
+ </span>
@@ -2,20 +2,17 @@
2
2
  <div class="row justify-content-center">
3
3
  <% contact_form ||= Spotlight::ContactForm.new current_url: request.original_url %>
4
4
  <%= bootstrap_form_for contact_form, url: spotlight.exhibit_contact_form_path(current_exhibit, contact_form), layout: :horizontal, label_col: 'col-sm-3', control_col: 'col-sm-9', html: { class: 'col-md-offset-2 col-md-8 my-3 '} do |f| %>
5
-
6
5
  <h2><%= t(:'.title') %></h2>
6
+ <div class="alert alert-primary"><%= t('.reporting_from', url: contact_form.current_url) %></div>
7
+ <%= f.text_area :message, rows: 4 %>
7
8
  <%= f.text_field :name %>
8
- <span style="display:none;visibility:hidden;">
9
- <% honeypot_field_name = Spotlight::Engine.config.spambot_honeypot_email_field %>
10
- <%= f.email_field honeypot_field_name, label: t(:'.honeypot_field_explanation') %>
11
- </span>
9
+ <%= render '/spotlight/shared/honeypot_field', f: f %>
12
10
  <%= f.email_field :email %>
13
- <%= f.text_area :message, rows: 7 %>
14
11
  <%= f.hidden_field :current_url %>
15
- <div class="form-actions">
16
- <div class="primary-actions">
17
- <%= link_to t(:'helpers.action.cancel'), '#', class: 'btn-sizing', data: { 'behavior' => 'cancel-link' } %>
18
- <%= f.submit nil, class: 'btn btn-primary' %>
12
+ <div class="form-actions row">
13
+ <div class="col offset-sm-3">
14
+ <%= f.submit nil, class: 'btn btn-primary' %>
15
+ <%= link_to t(:'helpers.action.cancel'), '#', class: 'btn-sizing', data: { 'behavior' => 'cancel-link' } %>
19
16
  </div>
20
17
  </div>
21
18
  <% end %>
@@ -34,6 +34,7 @@ ignore_unused:
34
34
  - activerecord.attributes.spotlight/page.{display_sidebar\?,display_title} # app/views/spotlight/home_pages/_page_options.html.erb
35
35
  - activerecord.attributes.spotlight/language.locale # app/views/spotlight/exhibits/_languages.html.erb
36
36
  - activerecord.attributes.spotlight/contact.avatar # app/views/spotlight/contacts/_form.html.erb
37
+ - activerecord.attributes.spotlight/exhibit.contact_emails # app/views/spotlight/exhibits/_form.html.erb
37
38
  - activerecord.attributes.spotlight/exhibit.published # app/views/spotlight/sites/_exhibit.html.erb
38
39
  - activerecord.attributes.spotlight/masthead.display # app/views/spotlight/appearances/edit.html.erb
39
40
  - activerecord.attributes.spotlight/custom_field.is_multiple # app/views/spotlight/custom_fields/_form.html.erb
@@ -66,6 +67,7 @@ ignore_unused:
66
67
  - helpers.submit.{submit,update} # Generically used set defaults
67
68
  - helpers.submit.contact.create # app/views/spotlight/contacts/_form.html.erb
68
69
  - helpers.action.exhibit.contact.submit # helpers.action.exhibit.contact.submit
70
+ - helpers.label.contact_form.{email,name} # app/views/spotlight/shared/_report_a_problem.html.erb
69
71
 
70
72
  # TODO Look into these as its unclear
71
73
  - activerecord.models.spotlight.page
@@ -16,25 +16,28 @@ ar:
16
16
  browse:
17
17
  search:
18
18
  item_count:
19
- one: 1 عنصر
19
+ zero: "%{count} عنصر"
20
+ one: "%{count} عنصر"
21
+ two: "%{count} عنصرين"
20
22
  few: "%{count} عناصر"
21
- many: "%{count} عناصر"
22
- other: "%{count} عناصر"
23
- two: عنصرين
24
- zero: لا يوجد
23
+ many: "%{count} عنصراً"
24
+ other: "%{count} عنصراً"
25
+
25
26
  search_box:
26
27
  label: ابحث في فئة التصفح الحالية
27
28
  placeholder: بحث...
28
29
  reset: مسح استعلام البحث
29
30
  submit: ابحث في فئة التصفح
30
31
  success:
31
- expand_html: يمكنك ايضاً <a href="%{expand_search_url}">البحث في كل مواد المعرض عن "%{browse_query}"</a>.
32
- result_number_html: طابق استعلام البحث <strong> %{search_size} من %{parent_search_count} عنصر</strong> في هذه الفئة.
32
+ expand_html: "يمكنك ايضاً <a href=\"%{expand_search_url}\">البحث في كل مواد المعرض عن \"%{browse_query}\"</a>."
33
+ result_number_html: "طابق استعلام البحث <strong> %{search_size} من %{parent_search_count} عنصر</strong> في هذه الفئة."
33
34
  zero_results:
34
- expand_html: تستطيع أن <a href="%{clear_search_url}"> تمسح استعلام البحث </a> أو محاولة <a href="%{expand_search_url}"> البحث في كل المواد المعروضة لاستعلام البحث ل"%{browse_query}"</a>
35
+ expand_html: "تستطيع أن <a href=\"%{clear_search_url}\"> تمسح استعلام البحث </a> أو محاولة <a href=\"%{expand_search_url}\"> البحث في كل المواد المعروضة لاستعلام البحث ل\"%{browse_query}\"</a>"
35
36
  result_number: لم يتطابق بحثك مع أي عنصر في هذه الفئة.
36
37
  header_links:
37
38
  contact: ملاحظات واقتراحات
39
+ login: تسجيل الدخول
40
+ logout: تسجيل الخروج
38
41
  shared:
39
42
  report_a_problem:
40
43
  honeypot_field_explanation: تجاهل هذا المربع النصي، فهو يُستخدم فقط لكشف المحتالين. إذا كتبت أي شيء في هذا المربع النصي، فلن يتم إرسال رسالتك.
@@ -43,17 +46,18 @@ ar:
43
46
  blocks:
44
47
  browse_block:
45
48
  items:
46
- one: 1 عنصر
49
+ zero: "%{count} عنصر"
50
+ one: "%{count} عنصر"
51
+ two: "%{count} عنصرين"
47
52
  few: "%{count} عناصر"
48
- many: "%{count} عناصر"
49
- other: "%{count} عناصر"
50
- two: عنصرين
51
- zero: لا يوجد
53
+ many: "%{count} عنصراً"
54
+ other: "%{count} عنصراً"
55
+
52
56
  link_to_search_block:
53
57
  items:
54
- one: 1 عنصر
58
+ zero: "%{count} عنصر"
59
+ one: "%{count} عنصر"
60
+ two: "%{count} عنصرين"
55
61
  few: "%{count} عناصر"
56
- many: "%{count} عناصر"
57
- other: "%{count} عناصر"
58
- two: عنصرين
59
- zero: لا يوجد
62
+ many: "%{count} عنصراً"
63
+ other: "%{count} عنصراً"