avo 2.20.0 → 2.21.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of avo might be problematic. Click here for more details.

Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -2
  3. data/app/components/avo/empty_state_component.html.erb +1 -1
  4. data/app/components/avo/empty_state_component.rb +12 -10
  5. data/app/components/avo/fields/belongs_to_field/edit_component.rb +1 -1
  6. data/app/components/avo/fields/boolean_field/edit_component.html.erb +1 -1
  7. data/app/components/avo/fields/boolean_group_field/edit_component.html.erb +1 -1
  8. data/app/components/avo/fields/code_field/edit_component.html.erb +2 -2
  9. data/app/components/avo/fields/country_field/edit_component.html.erb +1 -1
  10. data/app/components/avo/fields/date_field/edit_component.html.erb +2 -2
  11. data/app/components/avo/fields/date_time_field/edit_component.html.erb +2 -2
  12. data/app/components/avo/fields/edit_component.rb +4 -0
  13. data/app/components/avo/fields/external_image_field/edit_component.html.erb +1 -1
  14. data/app/components/avo/fields/file_field/edit_component.html.erb +1 -1
  15. data/app/components/avo/fields/files_field/edit_component.html.erb +1 -1
  16. data/app/components/avo/fields/has_one_field/show_component.html.erb +3 -3
  17. data/app/components/avo/fields/markdown_field/edit_component.html.erb +1 -1
  18. data/app/components/avo/fields/markdown_field/show_component.html.erb +1 -1
  19. data/app/components/avo/fields/number_field/edit_component.html.erb +1 -1
  20. data/app/components/avo/fields/password_field/edit_component.html.erb +1 -1
  21. data/app/components/avo/fields/progress_bar_field/edit_component.html.erb +1 -1
  22. data/app/components/avo/fields/select_field/edit_component.html.erb +1 -1
  23. data/app/components/avo/fields/show_component.rb +4 -0
  24. data/app/components/avo/fields/status_field/edit_component.html.erb +1 -1
  25. data/app/components/avo/fields/tags_field/edit_component.html.erb +2 -2
  26. data/app/components/avo/fields/text_field/edit_component.html.erb +1 -1
  27. data/app/components/avo/fields/textarea_field/edit_component.html.erb +1 -1
  28. data/app/components/avo/fields/time_field/edit_component.html.erb +2 -2
  29. data/app/components/avo/fields/trix_field/edit_component.html.erb +3 -2
  30. data/app/components/avo/fields/trix_field/edit_component.rb +5 -1
  31. data/app/components/avo/index/resource_grid_component.html.erb +1 -1
  32. data/app/components/avo/index/resource_table_component.rb +3 -3
  33. data/app/components/avo/paginator_component.html.erb +1 -5
  34. data/app/components/avo/paginator_component.rb +8 -0
  35. data/app/components/avo/resource_component.rb +17 -2
  36. data/app/components/avo/views/resource_index_component.html.erb +1 -1
  37. data/app/controllers/avo/application_controller.rb +2 -2
  38. data/app/controllers/avo/associations_controller.rb +2 -1
  39. data/app/controllers/avo/attachments_controller.rb +4 -0
  40. data/app/controllers/avo/base_controller.rb +10 -4
  41. data/app/controllers/avo/dashboards/cards_controller.rb +1 -1
  42. data/app/controllers/avo/search_controller.rb +11 -5
  43. data/app/javascript/js/controllers/fields/trix_field_controller.js +6 -3
  44. data/app/javascript/js/controllers/item_select_all_controller.js +7 -4
  45. data/app/views/avo/actions/show.html.erb +1 -1
  46. data/app/views/avo/base/_multiple_select_filter.html.erb +1 -1
  47. data/app/views/avo/partials/_resource_search.html.erb +1 -1
  48. data/config/i18n-tasks.yml +1 -1
  49. data/config/initializers/pagy.rb +16 -0
  50. data/lib/avo/base_action.rb +9 -3
  51. data/lib/avo/base_card.rb +5 -2
  52. data/lib/avo/base_resource.rb +3 -2
  53. data/lib/avo/concerns/handles_field_args.rb +8 -1
  54. data/lib/avo/fields/base_field.rb +2 -1
  55. data/lib/avo/fields/concerns/is_disabled.rb +19 -0
  56. data/lib/avo/fields/select_field.rb +1 -1
  57. data/lib/avo/filters/base_filter.rb +1 -2
  58. data/lib/avo/hosts/resource_record_host.rb +7 -0
  59. data/lib/avo/hosts/visibility_host.rb +0 -1
  60. data/lib/avo/services/authorization_service.rb +2 -2
  61. data/lib/avo/version.rb +1 -1
  62. data/lib/generators/avo/templates/field/components/edit_component.html.erb.tt +1 -1
  63. data/lib/generators/avo/templates/locales/avo.en.yml +3 -2
  64. data/lib/generators/avo/templates/locales/avo.fr.yml +3 -2
  65. data/lib/generators/avo/templates/locales/avo.nb.yml +3 -2
  66. data/lib/generators/avo/templates/locales/avo.nn.yml +3 -2
  67. data/lib/generators/avo/templates/locales/avo.pt-BR.yml +3 -2
  68. data/lib/generators/avo/templates/locales/avo.pt.yml +120 -0
  69. data/lib/generators/avo/templates/locales/avo.ro.yml +56 -55
  70. data/lib/generators/avo/templates/locales/avo.tr.yml +3 -2
  71. data/lib/generators/avo/templates/locales/pagy/nn.yml +15 -0
  72. data/lib/generators/avo/templates/locales/pagy/ro.yml +17 -0
  73. data/public/avo-assets/avo.base.js +2 -2
  74. data/public/avo-assets/avo.base.js.map +2 -2
  75. metadata +7 -2
@@ -44,27 +44,33 @@ module Avo
44
44
  end
45
45
 
46
46
  def search_resource(resource)
47
- query = Avo::Hosts::SearchScopeHost.new(
47
+ query = Avo::Hosts::SearchScopeHost.new(
48
48
  block: resource.search_query,
49
49
  params: params,
50
- scope: resource.class.scope.limit(8)
50
+ scope: resource.class.scope
51
51
  ).handle
52
52
 
53
+ # Get the count
54
+ results_count = query.count
55
+
56
+ # Get the results
57
+ query = query.limit(8)
58
+
53
59
  query = apply_scope(query) if should_apply_any_scope?
54
60
 
55
61
  results = apply_search_metadata(query, resource)
56
62
 
57
63
  header = resource.plural_name
58
64
 
59
- if results.length > 0
60
- header += " (#{results.length})"
65
+ if results_count > 0
66
+ header = "#{header} (#{results_count})"
61
67
  end
62
68
 
63
69
  result_object = {
64
70
  header: header,
65
71
  help: resource.class.search_query_help,
66
72
  results: results,
67
- count: results.length
73
+ count: results_count
68
74
  }
69
75
 
70
76
  [resource.name.pluralize.downcase, result_object]
@@ -55,7 +55,7 @@ export default class extends Controller {
55
55
  }
56
56
 
57
57
  // Prevent file uploads for resources that haven't been saved yet.
58
- if (this.resourceId === '') {
58
+ if (!this.resourceId) {
59
59
  event.preventDefault()
60
60
  alert("You can't upload files into the Trix editor until you save the resource.")
61
61
 
@@ -63,7 +63,7 @@ export default class extends Controller {
63
63
  }
64
64
 
65
65
  // Prevent file uploads for fields without an attachment key.
66
- if (this.attachmentKey === '') {
66
+ if (!this.attachmentKey) {
67
67
  event.preventDefault()
68
68
  alert("You haven't set an `attachment_key` to this Trix field.")
69
69
  }
@@ -93,7 +93,10 @@ export default class extends Controller {
93
93
 
94
94
  xhr.open('POST', this.uploadUrl, true)
95
95
 
96
- xhr.setRequestHeader('X-CSRF-Token', document.querySelector('meta[name="csrf-token"]').content)
96
+ const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content
97
+ if (csrfToken) {
98
+ xhr.setRequestHeader('X-CSRF-Token', csrfToken)
99
+ }
97
100
 
98
101
  xhr.upload.addEventListener('progress', (event) => {
99
102
  // eslint-disable-next-line no-mixed-operators
@@ -18,8 +18,7 @@ export default class extends Controller {
18
18
  document.querySelectorAll(`[data-controller="item-selector"][data-resource-name="${this.resourceName}"] input[type=checkbox]`)
19
19
  .forEach((checkbox) => checkbox.checked !== checked && checkbox.click())
20
20
 
21
- // Only run "all matching" if there are more pages available
22
- if (this.pageCountValue > 1) {
21
+ if (this.selectAllEnabled()) {
23
22
  this.selectAllOverlay(checked)
24
23
 
25
24
  // When de-selecting everything, ensure the selectAll toggle is false and hide overlay.
@@ -35,8 +34,7 @@ export default class extends Controller {
35
34
  this.itemCheckboxTargets.forEach((checkbox) => allSelected = allSelected && checkbox.checked)
36
35
  this.checkboxTarget.checked = allSelected
37
36
 
38
- // Only run "all matching" if there are more pages available
39
- if (this.pageCountValue > 1) {
37
+ if (this.selectAllEnabled()) {
40
38
  this.selectAllOverlay(allSelected)
41
39
  this.resetUnselected()
42
40
  }
@@ -63,4 +61,9 @@ export default class extends Controller {
63
61
  this.selectAllOverlayTarget.classList.add('hidden')
64
62
  }
65
63
  }
64
+
65
+ // True if there are more pages available and if query encryption run successfully
66
+ selectAllEnabled() {
67
+ return this.pageCountValue > 1 && this.selectedAllQueryValue !== 'select_all_disabled'
68
+ }
66
69
  }
@@ -18,7 +18,7 @@
18
18
  <%= @action.action_name %>
19
19
  <% end %>
20
20
  <div class="flex-1 flex">
21
- <%= @action.message %>
21
+ <%= @action.get_message %>
22
22
  </div>
23
23
  <%= form.hidden_field :avo_resource_ids, value: params[:resource_ids], 'data-action-target': 'resourceIds' %>
24
24
  <%= form.hidden_field :avo_selected_query, 'data-action-target': 'selectedAllQuery' %>
@@ -13,7 +13,7 @@
13
13
  %>
14
14
  <div class="flex justify-end">
15
15
  <%= a_button class: 'mt-4', color: :primary, size: :xs, data: { action: "multiple-select-filter#changeFilter" } do %>
16
- Filter by <%=filter.name %>
16
+ <%= "#{t("avo.filter_by")} #{filter.name}" %>
17
17
  <% end %>
18
18
  </div>
19
19
  <%= link_to 'url_redirect', request.url, data: { 'multiple-select-filter-target': 'urlRedirect', 'turbo-frame': params[:turbo_frame] }, style: 'hidden', class: 'hidden' %>
@@ -2,7 +2,7 @@
2
2
  <div class="w-full"
3
3
  data-search-target="autocomplete"
4
4
  data-search-resource="<%= resource %>"
5
- data-translation-keys='{"no_item_found": "<%= I18n.translate 'avo.no_item_found' %>"}'
5
+ data-translation-keys='{"no_item_found": "<%= I18n.translate 'avo.no_item_found' %>", "placeholder": "<%= I18n.translate 'avo.search.placeholder' %>", "cancel_button": "<%= I18n.translate 'avo.search.cancel_button' %>"}'
6
6
  <% if via_reflection.present? %>
7
7
  data-via-association="<%= via_reflection[:association] %>"
8
8
  data-via-association-id="<%= via_reflection[:association_id] %>"
@@ -3,7 +3,7 @@
3
3
  # The "main" locale.
4
4
  base_locale: en
5
5
  ## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
6
- locales: [en, fr, nb, nn, pt-BR, ro, tr]
6
+ locales: [en, fr, nb, nn, pt-BR, pt, ro, tr]
7
7
  ## Reporting locale, default: en. Available: en, ru.
8
8
  # internal_locale: en
9
9
 
@@ -1 +1,17 @@
1
1
  require "pagy/extras/trim"
2
+
3
+ # For locales without native pagy i18n support
4
+ def pagy_locale_path(file_name)
5
+ Avo::Engine.root.join("lib", "generators", "avo", "templates", "locales", "pagy", file_name)
6
+ end
7
+
8
+ Pagy::I18n.load(
9
+ { locale: 'en' },
10
+ { locale: 'fr' },
11
+ { locale: 'nb' },
12
+ { locale: 'pt-BR' },
13
+ { locale: 'pt' },
14
+ { locale: 'tr' },
15
+ { locale: 'nn', filepath: pagy_locale_path("nn.yml") },
16
+ { locale: 'ro', filepath: pagy_locale_path("ro.yml") },
17
+ )
@@ -72,6 +72,14 @@ module Avo
72
72
  @response[:messages] = []
73
73
  end
74
74
 
75
+ def get_message
76
+ if self.class.message.respond_to? :call
77
+ Avo::Hosts::ResourceRecordHost.new(block: self.class.message, record: self.class.model, resource: self.class.resource).handle
78
+ else
79
+ self.class.message
80
+ end
81
+ end
82
+
75
83
  def get_attributes_for_action
76
84
  get_fields.map do |field|
77
85
  [field.id, field.value || field.default]
@@ -116,7 +124,7 @@ module Avo
116
124
  self
117
125
  end
118
126
 
119
- def visible_in_view(parent_model: nil, parent_resource: nil)
127
+ def visible_in_view(parent_resource: nil)
120
128
  if visible.blank?
121
129
  # Hide on the :new view by default
122
130
  return false if view == :new
@@ -128,9 +136,7 @@ module Avo
128
136
  # Run the visible block if available
129
137
  Avo::Hosts::VisibilityHost.new(
130
138
  block: visible,
131
- model: self.class.model,
132
139
  params: params,
133
- parent_model: parent_model,
134
140
  parent_resource: parent_resource,
135
141
  resource: self.class.resource,
136
142
  view: self.class.view,
data/lib/avo/base_card.rb CHANGED
@@ -20,6 +20,10 @@ module Avo
20
20
  attr_accessor :params
21
21
 
22
22
  delegate :context, to: ::Avo::App
23
+ delegate :current_user, to: ::Avo::App
24
+ delegate :view_context, to: ::Avo::App
25
+ delegate :params, to: ::Avo::App
26
+ delegate :request, to: ::Avo::App
23
27
 
24
28
  class << self
25
29
  def query(&block)
@@ -106,9 +110,8 @@ module Avo
106
110
  self
107
111
  end
108
112
 
109
- def hydrate(dashboard: nil, params: nil)
113
+ def hydrate(dashboard: nil)
110
114
  @dashboard = dashboard if dashboard.present?
111
- @params = params if params.present?
112
115
 
113
116
  self
114
117
  end
@@ -117,9 +117,10 @@ module Avo
117
117
  end
118
118
 
119
119
  def valid_attachment_name(record, association_name)
120
- get_record_associations(record).keys.each do |name|
121
- return association_name if name == "#{association_name}_attachment" || name == "#{association_name}_attachments"
120
+ association_exists = get_record_associations(record).keys.any? do |name|
121
+ name == "#{association_name}_attachment" || name == "#{association_name}_attachments"
122
122
  end
123
+ return association_name if association_exists
123
124
  end
124
125
 
125
126
  def get_available_models
@@ -12,7 +12,14 @@ module Avo
12
12
  value = default
13
13
 
14
14
  if type == :boolean
15
- value = args[name.to_sym] == true
15
+ case args[name.to_sym]
16
+ when nil
17
+ value = default
18
+ when false
19
+ value = false
20
+ when true
21
+ value = true
22
+ end
16
23
  else
17
24
  value = args[name.to_sym] unless args.dig(name.to_sym).nil?
18
25
  end
@@ -10,10 +10,10 @@ module Avo
10
10
  include ActionView::Helpers::UrlHelper
11
11
  include Avo::Fields::FieldExtensions::VisibleInDifferentViews
12
12
 
13
- include Avo::Concerns::HandlesFieldArgs
14
13
  include Avo::Concerns::HasHTMLAttributes
15
14
  include Avo::Fields::Concerns::IsRequired
16
15
  include Avo::Fields::Concerns::IsReadonly
16
+ include Avo::Fields::Concerns::IsDisabled
17
17
  include Avo::Fields::Concerns::HasDefault
18
18
 
19
19
  delegate :view_context, to: ::Avo::App
@@ -65,6 +65,7 @@ module Avo
65
65
  @block = block
66
66
  @required = args.dig(:required) # Value if :required present on args, nil otherwise
67
67
  @readonly = args[:readonly] || false
68
+ @disabled = args[:disabled] || false
68
69
  @sortable = args[:sortable] || false
69
70
  @nullable = args[:nullable] || false
70
71
  @null_values = args[:null_values] || [nil, ""]
@@ -0,0 +1,19 @@
1
+ module Avo
2
+ module Fields
3
+ module Concerns
4
+ module IsDisabled
5
+ extend ActiveSupport::Concern
6
+
7
+ attr_reader :disabled
8
+
9
+ def is_disabled?
10
+ if disabled.respond_to? :call
11
+ Avo::Hosts::ResourceViewRecordHost.new(block: disabled, record: model, view: view, resource: resource).handle
12
+ else
13
+ disabled
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -58,7 +58,7 @@ module Avo
58
58
 
59
59
  # Cache options as options given on block or as options received from arguments
60
60
  def options
61
- @options ||= if options_from_args.respond_to? :call
61
+ if options_from_args.respond_to? :call
62
62
  options_from_args.call model: model, resource: resource, view: view, field: self
63
63
  else
64
64
  options_from_args
@@ -60,14 +60,13 @@ module Avo
60
60
  self.class.decode_filters params[PARAM_KEY]
61
61
  end
62
62
 
63
- def visible_in_view(resource: nil, parent_model: nil, parent_resource: nil)
63
+ def visible_in_view(resource: nil, parent_resource: nil)
64
64
  return true if visible.blank?
65
65
 
66
66
  # Run the visible block if available
67
67
  Avo::Hosts::VisibilityHost.new(
68
68
  block: visible,
69
69
  params: params,
70
- parent_model: parent_model,
71
70
  parent_resource: parent_resource,
72
71
  resource: resource,
73
72
  arguments: arguments
@@ -0,0 +1,7 @@
1
+ module Avo
2
+ module Hosts
3
+ class ResourceRecordHost < RecordHost
4
+ option :resource
5
+ end
6
+ end
7
+ end
@@ -1,7 +1,6 @@
1
1
  module Avo
2
2
  module Hosts
3
3
  class VisibilityHost < BaseHost
4
- option :parent_model
5
4
  option :parent_resource
6
5
  option :resource
7
6
  option :arguments
@@ -119,7 +119,7 @@ module Avo
119
119
  end
120
120
 
121
121
  def authorize_action(action, **args)
122
- self.class.authorize_action(user, record, action, policy_class: policy_class, **args)
122
+ self.class.authorize_action(user, args[:record] || record, action, policy_class: policy_class, **args)
123
123
  end
124
124
 
125
125
  def apply_policy(model)
@@ -131,7 +131,7 @@ module Avo
131
131
  end
132
132
 
133
133
  def has_method?(method, **args)
134
- defined_methods(record, **args).include? method.to_sym
134
+ defined_methods(args[:record] || record, **args).include? method.to_sym
135
135
  end
136
136
  end
137
137
  end
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.20.0" unless const_defined?(:VERSION)
2
+ VERSION = "2.21.0" unless const_defined?(:VERSION)
3
3
  end
@@ -2,5 +2,5 @@
2
2
  <%%= @form.text_field @field.id,
3
3
  class: classes("w-full"),
4
4
  placeholder: @field.placeholder,
5
- disabled: @field.is_readonly? %>
5
+ disabled: disabled? %>
6
6
  <%% end %>
@@ -46,6 +46,7 @@ en:
46
46
  one: peep
47
47
  other: peeps
48
48
  zero: peeps
49
+ filter_by: Filter by
49
50
  filters: Filters
50
51
  go_back: Go back
51
52
  grid_view: Grid view
@@ -62,9 +63,9 @@ en:
62
63
  new: new
63
64
  next_page: Next page
64
65
  no_cards_present: No cards present
65
- no_item_found: No %{item} found
66
+ no_item_found: No record found
66
67
  no_options_available: No options available
67
- no_related_item_found: No related %{item} found
68
+ no_related_item_found: No related record found
68
69
  not_authorized: You are not authorized to perform this action.
69
70
  number_of_items:
70
71
  one: one %{item}
@@ -46,6 +46,7 @@ fr:
46
46
  one: personne
47
47
  other: personnes
48
48
  zero: personne
49
+ filter_by: Filtrer par
49
50
  filters: Filtres
50
51
  go_back: Retourner en arrière
51
52
  grid_view: Vue grille
@@ -62,9 +63,9 @@ fr:
62
63
  new: Nouveau
63
64
  next_page: Page suivante
64
65
  no_cards_present: Aucune carte présente
65
- no_item_found: Aucun %{item} trouvé
66
+ no_item_found: Enregistrement non trouvé
66
67
  no_options_available: Aucune option disponible
67
- no_related_item_found: Aucun %{item} apparenté n'a été trouvé
68
+ no_related_item_found: Enregistrement connexe introuvable
68
69
  not_authorized: Vous n'êtes pas autorisé à effectuer cette action.
69
70
  number_of_items:
70
71
  one: un %{item}
@@ -46,6 +46,7 @@ nb:
46
46
  one: person
47
47
  other: personer
48
48
  zero: personer
49
+ filter_by: Filtrer etter
49
50
  filters: Filter
50
51
  go_back: Gå tilbake
51
52
  grid_view: Grid visning
@@ -62,9 +63,9 @@ nb:
62
63
  new: ny
63
64
  next_page: Neste side
64
65
  no_cards_present: Ingen kort til stede
65
- no_item_found: Ingen %{item} funnet
66
+ no_item_found: Ingen funnet
66
67
  no_options_available: Ingen tilgjengelige alternativer
67
- no_related_item_found: Ingen relaterte %{item} funnet
68
+ no_related_item_found: Ingen relaterte funnet
68
69
  not_authorized: Du er ikke autorisert til å gjøre denne handlingen.
69
70
  number_of_items:
70
71
  one: en %{item}
@@ -46,6 +46,7 @@ nn:
46
46
  one: person
47
47
  other: personar
48
48
  zero: personar
49
+ filter_by: Filtrer etter
49
50
  filters: Filter
50
51
  go_back: Gå tilbake
51
52
  grid_view: Gridvisning
@@ -62,9 +63,9 @@ nn:
62
63
  new: ny
63
64
  next_page: Neste side
64
65
  no_cards_present: Ingen kort til stades
65
- no_item_found: Fann ingen %{item}
66
+ no_item_found: Fann ingen
66
67
  no_options_available: Ingen tilgjengelege alternativ
67
- no_related_item_found: Fann ingen relaterte %{item}
68
+ no_related_item_found: Fann ingen relaterte
68
69
  not_authorized: Du er ikkje autorisert til å gjere denne handlinga.
69
70
  number_of_items:
70
71
  one: en %{item}
@@ -46,6 +46,7 @@ pt-BR:
46
46
  one: pessoa
47
47
  other: pessoas
48
48
  zero: ninguém
49
+ filter_by: Filtrar por
49
50
  filters: Filtros
50
51
  go_back: Voltar
51
52
  grid_view: Visualização em grade
@@ -62,9 +63,9 @@ pt-BR:
62
63
  new: novo
63
64
  next_page: Próxima página
64
65
  no_cards_present: Nenhum cartão presente
65
- no_item_found: Nenhum %{item} encontrado
66
+ no_item_found: Nenhum registro encontrado
66
67
  no_options_available: Nenhuma opção disponível
67
- no_related_item_found: Nenhum %{item} relacionado encontrado
68
+ no_related_item_found: Nenhum registro relacionado encontrado
68
69
  not_authorized: Você não está autorizado à executar essa ação.
69
70
  number_of_items:
70
71
  one: um %{item}
@@ -0,0 +1,120 @@
1
+ ---
2
+ pt:
3
+ avo:
4
+ action_ran_successfully: Ação executada com sucesso!
5
+ actions: Ações
6
+ and_x_other_resources: e %{count} outros recursos
7
+ are_you_sure: Tem a certeza?
8
+ are_you_sure_detach_item: Tem a certeza que deseja separar este %{item}.
9
+ are_you_sure_you_want_to_run_this_option: Tem a certeza que deseja executar esta ação?
10
+ attach: Anexar
11
+ attach_and_attach_another: Anexar & anexar outro
12
+ attach_item: Anexar %{item}
13
+ attachment_class_attached: "%{attachment_class} anexado."
14
+ attachment_class_detached: "%{attachment_class} separado."
15
+ attachment_destroyed: Anexo destruído
16
+ cancel: Cancelar
17
+ choose_a_country: Escolha um país
18
+ choose_an_option: Escolha uma opção
19
+ choose_item: Escolher %{item}
20
+ clear_value: Apagar valor
21
+ click_to_reveal_filters: Clique para mostrar os filtros
22
+ confirm: Confirmar
23
+ create_new_item: Criar novo %{item}
24
+ dashboard: Painel
25
+ dashboards: Painéis
26
+ delete: apagar
27
+ delete_file: Apagar arquivo
28
+ delete_item: Apagar %{item}
29
+ detach_item: separar %{item}
30
+ details: detalhe
31
+ download: Download
32
+ download_file: Download do ficheiro
33
+ download_item: Download %{item}
34
+ edit: editar
35
+ edit_item: editar %{item}
36
+ empty_dashboard_message: Adicionar cartões a este painel
37
+ failed: Falhou
38
+ failed_to_find_attachment: Falha ao encontrar anexo
39
+ failed_to_load: Falhou ao carregar
40
+ field_translations:
41
+ file:
42
+ one: ficheiro
43
+ other: ficheiros
44
+ zero: ficheiros
45
+ people:
46
+ one: pessoa
47
+ other: pessoas
48
+ zero: ninguém
49
+ filter_by: Filtrar por
50
+ filters: Filtros
51
+ go_back: Voltar
52
+ grid_view: Visualização em grelha
53
+ hide_content: Esconder conteúdo
54
+ home: Início
55
+ key_value_field:
56
+ add_row: Adicionar linha
57
+ delete_row: Apagar linha
58
+ key: Chave
59
+ value: Valor
60
+ list_is_empty: Lista vazia
61
+ loading: A carregar
62
+ more: Mais
63
+ new: novo
64
+ next_page: Próxima página
65
+ no_cards_present: Nenhum cartão presente
66
+ no_item_found: Nenhum registro encontrado
67
+ no_options_available: Nenhuma opção disponível
68
+ no_related_item_found: Nenhum registro relacionado encontrado
69
+ not_authorized: Não está autorizado a executar essa ação.
70
+ number_of_items:
71
+ one: um %{item}
72
+ other: "%{count} %{item}"
73
+ zero: sem %{item}
74
+ oops_nothing_found: Oops! Nada encontrado...
75
+ order:
76
+ higher: Mover recurso para cima
77
+ lower: Mover recuros para baixo
78
+ reorder_record: Reordenar recurso
79
+ to_bottom: Mover recurso para o fundo
80
+ to_top: Mover recurso para o topo
81
+ per_page: Por página
82
+ prev_page: Página anterior
83
+ remove_selection: Remover seleção
84
+ reset_filters: Limpar filtros
85
+ resource_created: Recurso criado
86
+ resource_destroyed: Recurso destruído
87
+ resource_translations:
88
+ user:
89
+ one: utilizador
90
+ other: utilizadores
91
+ zero: utilizadores
92
+ resource_updated: Recurso atualizado
93
+ resources: Recursos
94
+ run: Executar
95
+ save: Guardar
96
+ search:
97
+ cancel_button: Cancelar
98
+ placeholder: Procurar
99
+ select_all: Selecionar tudo
100
+ select_all_matching: Selecionar todas as correspondências
101
+ select_item: Selecionar item
102
+ show_content: Mostrar conteúdo
103
+ sign_out: Terminar sessão
104
+ switch_to_view: Alterar para visão %{view_type}
105
+ table_view: Visualização em tabela
106
+ tools: Ferramentas
107
+ type_to_search: Escreva para pesquisar.
108
+ unauthorized: Não autorizado
109
+ undo: desfazer
110
+ view: Ver
111
+ view_item: ver %{item}
112
+ was_successfully_created: foi criado com sucesso
113
+ was_successfully_updated: foi atualizado com sucesso
114
+ x_items_more:
115
+ one: mais um item
116
+ other: "%{count} mais items"
117
+ zero: mais nenhum item
118
+ x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> itens selecionados nesta página de um total de <span class="font-bold text-gray-700">%{count}</span>
119
+ x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> itens selecionados de todas as páginas
120
+ you_missed_something_check_form: Pode ter-se esquecido algo. Por favor, verifique o formulário.