decidim-core 0.27.0.rc2 → 0.27.1

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

Potentially problematic release.


This version of decidim-core might be problematic. Click here for more details.

Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/amendable/announcement_cell.rb +1 -1
  3. data/app/cells/decidim/card_m_cell.rb +1 -1
  4. data/app/controllers/decidim/devise/invitations_controller.rb +9 -2
  5. data/app/controllers/decidim/last_activities_controller.rb +5 -2
  6. data/app/forms/decidim/account_form.rb +2 -2
  7. data/app/forms/decidim/amendable/form.rb +2 -1
  8. data/app/forms/decidim/registration_form.rb +2 -2
  9. data/app/forms/decidim/upload_validation_form.rb +51 -7
  10. data/app/helpers/decidim/layout_helper.rb +12 -4
  11. data/app/helpers/decidim/sanitize_helper.rb +1 -1
  12. data/app/mailers/decidim/notification_mailer.rb +1 -0
  13. data/app/mailers/decidim/notifications_digest_mailer.rb +1 -0
  14. data/app/packs/src/decidim/editor/clipboard_override.js +143 -0
  15. data/app/packs/src/decidim/editor/clipboard_utilities.js +119 -0
  16. data/app/packs/src/decidim/editor/linebreak_module.js +0 -8
  17. data/app/packs/src/decidim/editor.js +9 -2
  18. data/app/packs/stylesheets/decidim/_editor.scss +129 -0
  19. data/app/packs/stylesheets/decidim/extras/_quill.scss +0 -6
  20. data/app/presenters/decidim/home_stats_presenter.rb +11 -4
  21. data/app/presenters/decidim/stats_presenter.rb +7 -8
  22. data/app/presenters/decidim/user_presenter.rb +9 -4
  23. data/app/queries/decidim/public_activities.rb +1 -0
  24. data/app/validators/etiquette_validator.rb +7 -3
  25. data/app/validators/file_content_type_validator.rb +103 -0
  26. data/app/validators/passthru_validator.rb +11 -0
  27. data/app/validators/uploader_content_type_validator.rb +22 -0
  28. data/app/views/decidim/notification_mailer/event_received.html.erb +1 -1
  29. data/app/views/decidim/notifications_digest_mailer/_email_content.html.erb +1 -1
  30. data/config/locales/ar.yml +0 -15
  31. data/config/locales/bg.yml +1 -14
  32. data/config/locales/ca.yml +7 -15
  33. data/config/locales/cs.yml +14 -22
  34. data/config/locales/de.yml +1 -14
  35. data/config/locales/el.yml +0 -13
  36. data/config/locales/en.yml +5 -13
  37. data/config/locales/es-MX.yml +6 -14
  38. data/config/locales/es-PY.yml +6 -14
  39. data/config/locales/es.yml +11 -19
  40. data/config/locales/eu.yml +7 -16
  41. data/config/locales/fi-plain.yml +5 -13
  42. data/config/locales/fi.yml +5 -13
  43. data/config/locales/fr-CA.yml +6 -14
  44. data/config/locales/fr.yml +6 -14
  45. data/config/locales/ga-IE.yml +1 -3
  46. data/config/locales/gl.yml +0 -15
  47. data/config/locales/gn-PY.yml +1 -0
  48. data/config/locales/hu.yml +21 -14
  49. data/config/locales/id-ID.yml +0 -15
  50. data/config/locales/is-IS.yml +2 -1
  51. data/config/locales/it.yml +2 -15
  52. data/config/locales/ja.yml +6 -14
  53. data/config/locales/lb.yml +0 -13
  54. data/config/locales/lo-LA.yml +1 -0
  55. data/config/locales/lt.yml +0 -13
  56. data/config/locales/lv.yml +0 -13
  57. data/config/locales/nl.yml +2 -15
  58. data/config/locales/no.yml +0 -13
  59. data/config/locales/oc-FR.yml +1 -0
  60. data/config/locales/pl.yml +1 -14
  61. data/config/locales/pt-BR.yml +2 -15
  62. data/config/locales/pt.yml +1 -14
  63. data/config/locales/ro-RO.yml +0 -13
  64. data/config/locales/ru.yml +0 -4
  65. data/config/locales/sk.yml +0 -16
  66. data/config/locales/sv.yml +0 -13
  67. data/config/locales/tr-TR.yml +2 -15
  68. data/config/locales/uk.yml +1 -2
  69. data/config/locales/zh-CN.yml +0 -13
  70. data/lib/decidim/attributes/localized_date.rb +1 -1
  71. data/lib/decidim/attributes/time_with_zone.rb +5 -2
  72. data/lib/decidim/core/engine.rb +7 -5
  73. data/lib/decidim/core/test/shared_examples/comments_examples.rb +1 -1
  74. data/lib/decidim/core/test/shared_examples/editor_shared_examples.rb +30 -0
  75. data/lib/decidim/core/test/shared_examples/mcell_examples.rb +17 -0
  76. data/lib/decidim/core/test.rb +2 -0
  77. data/lib/decidim/core/version.rb +1 -1
  78. data/lib/decidim/file_validator_humanizer.rb +1 -1
  79. data/lib/decidim/form_builder.rb +10 -3
  80. data/lib/decidim/resourceable.rb +5 -4
  81. data/lib/decidim/settings_manifest.rb +1 -1
  82. metadata +16 -9
  83. data/app/packs/images/decidim/gamification/badges/decidim_gamification_badges_invitations.svg +0 -1
@@ -10,4 +10,133 @@
10
10
  margin-bottom: $paragraph-margin-bottom;
11
11
  text-rendering: $paragraph-text-rendering;
12
12
  }
13
+
14
+ ul,
15
+ ol{
16
+ margin-bottom: $paragraph-margin-bottom;
17
+ }
18
+ }
19
+
20
+ .ql-editor-display{
21
+ ul,
22
+ ol{
23
+ li{
24
+ list-style-type: none;
25
+ margin-bottom: .5rem;
26
+
27
+ &::before{
28
+ content: "\2022";
29
+ display: inline-block;
30
+ white-space: nowrap;
31
+ width: 1.2em;
32
+ }
33
+
34
+ &.ql-indent-1{
35
+ padding-left: 3em;
36
+ }
37
+
38
+ &.ql-indent-2{
39
+ padding-left: 6em;
40
+ }
41
+
42
+ &.ql-indent-3{
43
+ padding-left: 9em;
44
+ }
45
+
46
+ &.ql-indent-4{
47
+ padding-left: 12em;
48
+ }
49
+
50
+ &.ql-indent-5{
51
+ padding-left: 15em;
52
+ }
53
+
54
+ &.ql-indent-6{
55
+ padding-left: 18em;
56
+ }
57
+
58
+ &.ql-indent-7{
59
+ padding-left: 21em;
60
+ }
61
+
62
+ &.ql-indent-8{
63
+ padding-left: 24em;
64
+ }
65
+
66
+ &.ql-indent-9{
67
+ padding-left: 27em;
68
+ }
69
+ }
70
+ }
71
+
72
+ ol{
73
+ li{
74
+ counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
75
+ counter-increment: list-0;
76
+
77
+ &::before{ content: counter(list-0, decimal) ". "; }
78
+
79
+ &.ql-indent-1{
80
+ counter-increment: list-1;
81
+ counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
82
+
83
+ &::before{ content: counter(list-1, lower-alpha) ". "; }
84
+ }
85
+
86
+ &.ql-indent-2{
87
+ counter-increment: list-2;
88
+ counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9;
89
+
90
+ &::before{ content: counter(list-2, lower-roman) ". "; }
91
+ }
92
+
93
+ &.ql-indent-3{
94
+ counter-increment: list-3;
95
+ counter-reset: list-4 list-5 list-6 list-7 list-8 list-9;
96
+
97
+ &::before{ content: counter(list-3, decimal) ". "; }
98
+ }
99
+
100
+ &.ql-indent-4{
101
+ counter-increment: list-4;
102
+ counter-reset: list-5 list-6 list-7 list-8 list-9;
103
+
104
+ &::before{ content: counter(list-4, lower-alpha) ". "; }
105
+ }
106
+
107
+ &.ql-indent-5{
108
+ counter-increment: list-5;
109
+ counter-reset: list-6 list-7 list-8 list-9;
110
+
111
+ &::before{ content: counter(list-5, lower-roman) ". "; }
112
+ }
113
+
114
+ &.ql-indent-6{
115
+ counter-increment: list-6;
116
+ counter-reset: list-7 list-8 list-9;
117
+
118
+ &::before{ content: counter(list-6, decimal) ". "; }
119
+ }
120
+
121
+ &.ql-indent-7{
122
+ counter-increment: list-7;
123
+ counter-reset: list-8 list-9;
124
+
125
+ &::before{ content: counter(list-7, lower-alpha) ". "; }
126
+ }
127
+
128
+ &.ql-indent-8{
129
+ counter-increment: list-8;
130
+ counter-reset: list-9;
131
+
132
+ &::before{ content: counter(list-8, lower-roman) ". "; }
133
+ }
134
+
135
+ &.ql-indent-9{
136
+ counter-increment: list-9;
137
+
138
+ &::before{ content: counter(list-9, decimal) ". "; }
139
+ }
140
+ }
141
+ }
13
142
  }
@@ -11,9 +11,3 @@
11
11
  margin-top: 0;
12
12
  margin-bottom: 0;
13
13
  }
14
-
15
- .ql-reset-decidim{
16
- display: inline;
17
- padding: 0;
18
- white-space: inherit;
19
- }
@@ -42,12 +42,19 @@ module Decidim
42
42
  end
43
43
 
44
44
  def component_stats(conditions)
45
+ stats = {}
45
46
  Decidim.component_manifests.flat_map do |component|
46
- component.stats.except([:supports_count])
47
- .filter(conditions)
48
- .with_context(published_components)
49
- .map { |name, data| [name, data] }
47
+ component
48
+ .stats.except([:supports_count])
49
+ .filter(conditions)
50
+ .with_context(published_components)
51
+ .each do |name, data|
52
+ stats[name] ||= 0
53
+ stats[name] += data
54
+ end
50
55
  end
56
+
57
+ stats.to_a
51
58
  end
52
59
 
53
60
  def published_components
@@ -15,18 +15,17 @@ module Decidim
15
15
  end
16
16
 
17
17
  def statistics(grouped_stats)
18
- statistics = []
18
+ statistics = {}
19
+
19
20
  grouped_stats.each do |_manifest_name, stats|
20
- stats.each_with_index.each do |stat, _index|
21
- stat.each_with_index.map do |_item, subindex|
22
- next unless (subindex % 3).zero?
23
- next if stat[subindex + 2].zero?
21
+ stats.each do |_space_manifest, component_manifest, count|
22
+ next if count.zero?
24
23
 
25
- statistics << { stat_title: stat[subindex + 1], stat_number: stat[subindex + 2] }
26
- end
24
+ statistics[component_manifest] ||= 0
25
+ statistics[component_manifest] += count
27
26
  end
28
27
  end
29
- statistics
28
+ statistics.map { |key, number| { stat_title: key, stat_number: number } }
30
29
  end
31
30
  end
32
31
  end
@@ -5,7 +5,6 @@ module Decidim
5
5
  # Decorator for users
6
6
  #
7
7
  class UserPresenter < SimpleDelegator
8
- include Rails.application.routes.mounted_helpers
9
8
  include ActionView::Helpers::UrlHelper
10
9
  include Decidim::TranslatableAttributes
11
10
 
@@ -27,7 +26,7 @@ module Decidim
27
26
  def profile_url
28
27
  return "" if respond_to?(:deleted?) && deleted?
29
28
 
30
- decidim.profile_url(__getobj__.nickname, host: __getobj__.organization.host)
29
+ decidim.profile_url(__getobj__.nickname)
31
30
  end
32
31
 
33
32
  def avatar
@@ -36,13 +35,13 @@ module Decidim
36
35
 
37
36
  def avatar_url(variant = nil)
38
37
  return default_avatar_url if __getobj__.blocked?
39
- return avatar.default_url unless avatar.attached?
38
+ return default_avatar_url unless avatar.attached?
40
39
 
41
40
  avatar.path(variant: variant)
42
41
  end
43
42
 
44
43
  def default_avatar_url
45
- attached_uploader(:avatar).default_url
44
+ avatar.default_url
46
45
  end
47
46
 
48
47
  def profile_path
@@ -77,5 +76,11 @@ module Decidim
77
76
  def has_tooltip?
78
77
  true
79
78
  end
79
+
80
+ private
81
+
82
+ def decidim
83
+ @decidim ||= Decidim::EngineRouter.new("decidim", { host: __getobj__.organization.host })
84
+ end
80
85
  end
81
86
  end
@@ -107,6 +107,7 @@ module Decidim
107
107
  LEFT JOIN decidim_participatory_space_private_users AS #{manifest.name}_private_users
108
108
  ON #{manifest.name}_private_users.privatable_to_type = '#{manifest.model_class_name}'
109
109
  AND #{table}.id = #{manifest.name}_private_users.privatable_to_id
110
+ AND #{table}.private_space = 't'
110
111
  SQL
111
112
  ).to_s
112
113
  ).where(
@@ -3,12 +3,16 @@
3
3
  # This validator takes care of ensuring the validated content is
4
4
  # respectful, doesn't use caps, and overall is meaningful.
5
5
  class EtiquetteValidator < ActiveModel::EachValidator
6
+ include ActionView::Helpers::SanitizeHelper
7
+
6
8
  def validate_each(record, attribute, value)
7
9
  return if value.blank?
8
10
 
9
- validate_caps(record, attribute, value)
10
- validate_marks(record, attribute, value)
11
- validate_caps_first(record, attribute, value)
11
+ text_value = strip_tags(value)
12
+
13
+ validate_caps(record, attribute, text_value)
14
+ validate_marks(record, attribute, text_value)
15
+ validate_caps_first(record, attribute, text_value)
12
16
  end
13
17
 
14
18
  private
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ # We need to define the validator in the `ActiveModel::Validations` namespace as
4
+ # this is what the `file_validators` uses and this is what gets priority over
5
+ # the root namespace class.
6
+ module ActiveModel
7
+ module Validations
8
+ # This validator provides content type validation for uploaded files. Extends
9
+ # the validator provided by the `file_validators` gem by fixing some weird
10
+ # messages in that validator.
11
+ class FileContentTypeValidator
12
+ private
13
+
14
+ alias mark_invalid_original mark_invalid unless private_method_defined?(:mark_invalid_original)
15
+
16
+ # This fixes the "weird" error messages such as "(?-mix:image\\/.*)" because
17
+ # this is the notation Regexp#to_s will return. Instead, we want to show the
18
+ # inner contents of the regular expressions.
19
+ #
20
+ # @see ActiveModel::Validations::FileContentTypeValidator#mark_invalid
21
+ def mark_invalid(record, attribute, error, option_types)
22
+ mark_invalid_original(record, attribute, error, invalid_types(option_types))
23
+ end
24
+
25
+ # Converts the configured content type matches to extensions if extensions are
26
+ # recognized for the specified content type and if not, the content type
27
+ # string itself.
28
+ #
29
+ # @param option_types [Array<Regexp, String>] Array of configured types.
30
+ # @param allowed_extensions [Array<String>, nil] Array of allowed extensions
31
+ # or nil if all extensions are "allowed" (in case we want to show the
32
+ # denylist error or hard code the types).
33
+ # @return [Array<String>] The invalid types as strings.
34
+ def invalid_types(option_types, allowed_extensions = nil)
35
+ extensions = []
36
+ content_types = []
37
+ option_types.each do |type|
38
+ # Since the original content types may have endings such as image/.*?, we
39
+ # want to replace the regexp pattern just with a star with the fallback
40
+ # option.
41
+ content_type = (type.try(:source) || type.to_s).gsub(".*?", "*")
42
+ if (exts = content_type_extensions(content_type, allowed_extensions))
43
+ extensions += exts
44
+ else
45
+ content_types << content_type
46
+ end
47
+ end
48
+
49
+ extensions.sort + content_types.sort
50
+ end
51
+
52
+ # Resolves the content type extensions through MiniMime or looks up all the
53
+ # possible extensions for wildcard content types such as `image/*`. For the
54
+ # wildcard extension types only those listed in the `allowed_extensions` will
55
+ # be returned.
56
+ #
57
+ # @param content_type [String] The content type, such as application/pdf or
58
+ # image/*.
59
+ # @param allowed_extensions [Array, nil] Array of allowed extensions
60
+ # or nil if all extensions are "allowed" (in case we want to show the
61
+ # denylist error or hard code the types).
62
+ # @return [Array<String>, nil] An array of the allowed extensions or nil when
63
+ # no extensions could be found.
64
+ def content_type_extensions(content_type, allowed_extensions = nil)
65
+ extensions =
66
+ if content_type.ends_with?("/*")
67
+ main_type = content_type.split("/")[0]
68
+ extensions_matching(%r{#{main_type}/.*})
69
+ else
70
+ extensions_matching(content_type)
71
+ end
72
+ return if extensions.count.zero?
73
+ return extensions unless allowed_extensions
74
+
75
+ extensions & allowed_extensions
76
+ end
77
+
78
+ # Looks up the extensions matching the content type lookup based on the
79
+ # MiniMime content types.
80
+ #
81
+ # @param content_type_lookup [String, Regexp] The lookup to be matched
82
+ # against.
83
+ # @return [Array<String>] The array of extensions.
84
+ def extensions_matching(content_type_lookup)
85
+ extensions = []
86
+ File.open(MiniMime::Configuration.ext_db_path).each do |line|
87
+ info = line.split(/\s+/)
88
+ next unless info[1].match?(content_type_lookup)
89
+
90
+ extensions << info[0]
91
+ end
92
+
93
+ extensions
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ # This is just to make Zeitwerk happy. The actual validator that gets priority
100
+ # is the class above as all validators in the `ActiveModel::Validations`
101
+ # namespace will be used primarily and only if a matching validator is not found
102
+ # in that namespace, the ones at the root level are used.
103
+ class FileContentTypeValidator < ActiveModel::Validations::FileContentTypeValidator; end
@@ -62,9 +62,20 @@ class PassthruValidator < ActiveModel::EachValidator
62
62
  elsif dummy.respond_to?(:organization=) && record.respond_to?(:organization)
63
63
  dummy.organization = record.organization
64
64
  end
65
+ validation_record_context(dummy, record)
65
66
  dummy
66
67
  end
67
68
 
69
+ def validation_record_context(dummy, record)
70
+ if dummy.is_a?(Decidim::Form)
71
+ dummy.with_context(
72
+ current_organization: record.try(:current_organization) || record.try(:ganization),
73
+ current_participatory_space: record.try(:current_participatory_space) || record.try(:participatory_space),
74
+ current_component: record.try(:current_component) || record.try(:component)
75
+ )
76
+ end
77
+ end
78
+
68
79
  def target_validators(attribute)
69
80
  target_class.validators_on(target_attribute(attribute))
70
81
  end
@@ -41,4 +41,26 @@ class UploaderContentTypeValidator < ActiveModel::Validations::FileContentTypeVa
41
41
  # rubocop: enable Metrics/CyclomaticComplexity
42
42
 
43
43
  def check_validity!; end
44
+
45
+ private
46
+
47
+ # This fixes the "weird" error messages such as "(?-mix:image\\/.*)" because
48
+ # this is the notation Regexp#to_s will return. Instead, we want to show the
49
+ # inner contents of the regular expressions.
50
+ #
51
+ # @see ActiveModel::Validations::FileContentTypeValidator#mark_invalid
52
+ def mark_invalid(record, attribute, error, option_types)
53
+ allowed_extensions = nil
54
+ if error == :allowed_file_content_types
55
+ uploader = record.attached_uploader(attribute) if record.respond_to?(:attached_uploader)
56
+ allowed_extensions =
57
+ # Note that this may be a private method in some uploaders.
58
+ if uploader && uploader.respond_to?(:extension_allowlist, true)
59
+ uploader.send(:extension_allowlist)
60
+ else
61
+ Decidim.organization_settings(record).upload_allowed_file_extensions
62
+ end
63
+ end
64
+ mark_invalid_original(record, attribute, error, invalid_types(option_types, allowed_extensions))
65
+ end
44
66
  end
@@ -4,7 +4,7 @@
4
4
 
5
5
  <% if @event_instance.resource_path.present? && @event_instance.resource_title.present? %>
6
6
  <p class="email-button email-button__cta">
7
- <%= link_to @event_instance.resource_title, @event_instance.resource_url %>
7
+ <%= link_to decidim_sanitize(@event_instance.resource_title, strip_tags: true), @event_instance.resource_url %>
8
8
  </p>
9
9
  <% end %>
10
10
 
@@ -5,7 +5,7 @@
5
5
  </p>
6
6
  <% if notification.resource_path.present? && notification.resource_title.present? %>
7
7
  <p class="email-button email-button__cta">
8
- <%= link_to notification.resource_title, notification.resource_url %>
8
+ <%= link_to decidim_sanitize(notification.resource_title, strip_tags: true), notification.resource_url %>
9
9
  </p>
10
10
  <% end %>
11
11
  </div>
@@ -654,18 +654,6 @@ ar:
654
654
  how: كيف يمكنك كسب ذلك
655
655
  page_description: الشارات عبارة عن اعتراف بإجراءات المشارك والتقدم في المنصة. عند البدء في الاكتشاف والمشاركة والتفاعل في المنصة ، ستربح شارات مختلفة. فيما يلي قائمة بالشارات وبعض الطرق التي يمكنك من خلالها كسبها.
656
656
  title: شارات
657
- invitations:
658
- conditions:
659
- - استخدم رابط "دعوة الأصدقاء" في صفحة المستخدم الخاصة بك لدعوة أصدقائك
660
- - تخصيص ، إذا كنت تريد ، الرسالة التي ترسلها
661
- - ستصل إلى أعلى مستوى عن طريق إرسال الدعوات وتسجيلها.
662
- description: تُمنح هذه الشارة عند قيامك بدعوة بعض الأشخاص وقضاء بعض الوقت للتسجيل في %{organization_name} وتصبح مشاركًا. شكرًا لك على تعريف شخص %{organization_name} للآخرين والمساعدة في توسيع نطاق المجتمع!
663
- description_another: قام هذا المشارك بدعوة %{score} شخصًا.
664
- description_own: لقد قمت بدعوة %{score} شخصًا.
665
- name: دعوات
666
- next_level_in: دعوة %{score} أشخاص آخرين للوصول إلى المستوى التالي!
667
- unearned_another: هذا المشارك لم يدع أي شخص حتى الآن
668
- unearned_own: لم تقم بدعوة أي شخص حتى الآن.
669
657
  description: الشارات عبارة عن اعتراف بإجراءات المشارك والتقدم في المنصة. عند البدء في الاكتشاف والمشاركة والتفاعل في المنصة ، ستربح شارات مختلفة.
670
658
  level: المستوى %{level}
671
659
  reached_top: لقد وصلت إلى المستوى الأعلى لهذه الشارة.
@@ -824,12 +812,10 @@ ar:
824
812
  title: المحادثات
825
813
  reply:
826
814
  send: إرسال
827
- title: رد
828
815
  show:
829
816
  title: المحادثة مع %{usernames}
830
817
  start:
831
818
  send: إرسال
832
- title: بدء محادثة
833
819
  metrics:
834
820
  followers:
835
821
  description: عدد المشاركين الذين يتبعون مساحة المشاركة هذه
@@ -1270,7 +1256,6 @@ ar:
1270
1256
  not_locked: لم يكن مغلقا
1271
1257
  too_many_marks: يستخدم الكثير من علامات الترقيم المتتالية (مثل! و؟)
1272
1258
  too_much_caps: يستخدم عددًا كبيرًا جدًا من الأحرف الكبيرة (أكثر من 25٪ من النص)
1273
- too_short: قصير جدًا (أقل من 15 حرفًا)
1274
1259
  forms:
1275
1260
  required: مطلوب
1276
1261
  invisible_captcha:
@@ -643,18 +643,6 @@ bg:
643
643
  how: Как може да я заслужите
644
644
  page_description: Значките са признания за действия на участниците и напредък в платформата. Когато започнете да откривате, участвате и взаимодействате в платформата, ще заслужите различни значки. Ето списъка със значки и някои начини, по които можете да ги заслужите.
645
645
  title: Значки
646
- invitations:
647
- conditions:
648
- - Използвайте връзката "покани приятели" на своята страница, за да поканите приятелите си
649
- - Персонализирайте, ако жеаете, съобщението, което изпращате
650
- - Ще се повишите нивото си, като изпращате покани и те бъдат регистрирани.
651
- description: Тази значка се предоставя, когато поканите някои хора и те отделят малко време да се регистрират в %{organization_name} и станат участници. Благодарим ви, че разказвате за %{organization_name} и така помогнете за разширяването на общността!
652
- description_another: Този участник покани %{score} човека.
653
- description_own: Вие поканихте %{score} човека.
654
- name: Покани
655
- next_level_in: Поканете още %{score} за да достигнете следващо ниво!
656
- unearned_another: Този участник все още не е поканил никой.
657
- unearned_own: Не сте поканил(а) никого все ще.
658
646
  description: Значките са признания за действия на участниците и напредък в платформата. Когато започнете да откривате, участвате и взаимодействате в платформата, ще спечелите различни значки.
659
647
  level: Ниво %{level}
660
648
  reached_top: Достигнахте максималното ниво на значката.
@@ -845,7 +833,7 @@ bg:
845
833
  title: Разговор с %{usernames}
846
834
  start:
847
835
  send: Изпрати
848
- title: Започнете разговор
836
+ title: Започни разговор
849
837
  metrics:
850
838
  followers:
851
839
  description: Брой участници, които следват това пространство
@@ -1334,7 +1322,6 @@ bg:
1334
1322
  other: 'При обработката на заявката Ви имаше няколко грешки:'
1335
1323
  too_many_marks: използва твърде много последователни препинателни знаци (напр. ! и ?)
1336
1324
  too_much_caps: използва твърде много главни букви (над 25% от текста)
1337
- too_short: е твърде къс (под 15 знака)
1338
1325
  forms:
1339
1326
  required: Задължително
1340
1327
  invisible_captcha:
@@ -30,6 +30,7 @@ ca:
30
30
  password_confirmation: Confirma la teva contrasenya
31
31
  personal_url: URL personal
32
32
  remove_avatar: Elimina la imatge de perfil
33
+ tos_agreement: Acord de termes i condicions d'ús
33
34
  models:
34
35
  decidim/attachment_created_event: Arxiu adjunt
35
36
  decidim/component_published_event: Component actiu
@@ -820,6 +821,8 @@ ca:
820
821
  allowed_file_extensions: 'Tipus de fitxers admesos: %{extensions}'
821
822
  max_file_dimension: 'Mides máximes de l''arxiu: %{resolution} pixels'
822
823
  max_file_size: 'Mida màxima del fitxer:%{megabytes}MB'
824
+ files:
825
+ extension_allowlist: 'Formats acceptats: %{extensions}'
823
826
  upload:
824
827
  labels:
825
828
  add_attachment: Afegir adjunt
@@ -858,18 +861,6 @@ ca:
858
861
  how: Com pots aconseguir-la
859
862
  page_description: Les insígnies són reconeixements de les accions de les participants i del progrés en la plataforma. A mesura que comencis a descobrir, participar i interactuar amb la plataforma, n'obtindràs de diferents tipus. Aquí tens la llista d'insígnies i algunes formes d'aconseguir-les.
860
863
  title: Insígnies
861
- invitations:
862
- conditions:
863
- - Utilitza l'enllaç "convidar amigues" a la teva pàgina d'usuària per convidar a les teves amistats
864
- - Personalitza, si vols, el missatge que estàs enviant
865
- - Pujaràs per mitjà de l'enviament d'invitacions i de registrar-les.
866
- description: Aquesta insígna s'aconsegueix quan has convidat a algunes persones a la plataforma %{organization_name}, i s'hi han registrat com a participants. Gràcies per donar a conèixer %{organization_name} a d'altres i ajudar a ampliar la comunitat!
867
- description_another: Aquesta participant ha convidat a %{score} persones.
868
- description_own: Has convidat %{score} persones.
869
- name: Invitacions
870
- next_level_in: Convida a %{score} persones més per arribar al següent nivell!
871
- unearned_another: Aquesta participant encara no ha convidat ningú.
872
- unearned_own: Encara no has convidat a ningú.
873
864
  description: Les insígnies són reconeixements de les accions de les participants i del progrés en la plataforma. A mesura que comencis a descobrir, participar i interactuar amb la plataforma, n'obtindràs de diferents tipus.
874
865
  level: Nivell %{level}
875
866
  reached_top: Has arribat al màxim nivell d'aquesta insígnia.
@@ -1081,7 +1072,7 @@ ca:
1081
1072
  reply:
1082
1073
  placeholder: La teva resposta...
1083
1074
  send: Enviar
1084
- title: Respon
1075
+ title: Respondre
1085
1076
  show:
1086
1077
  back: Tornar a totes les converses
1087
1078
  chat_with: Conversa amb
@@ -1090,7 +1081,7 @@ ca:
1090
1081
  title: Conversa amb %{usernames}
1091
1082
  start:
1092
1083
  send: Enviar
1093
- title: Comença una conversa
1084
+ title: Iniciar una conversa
1094
1085
  update:
1095
1086
  error: El missatge no ha estat enviat degut a un error
1096
1087
  metrics:
@@ -1685,6 +1676,7 @@ ca:
1685
1676
  public: La teva informació pública.
1686
1677
  errors:
1687
1678
  messages:
1679
+ allowed_file_content_types: 'Només s''accepten arxius amb les següents extensions: %{types}'
1688
1680
  already_confirmed: ja s'ha confirmat, si us plau intenta iniciar la sessió
1689
1681
  confirmation_period_expired: s'ha de confirmar dins de %{period}, si us plau sol·licita'n un de nou
1690
1682
  content_type_allowlist_error: el tipus de fitxer no és vàlid
@@ -1702,7 +1694,7 @@ ca:
1702
1694
  other: 'S''han produït múltiples errors en processar la vostra sol·licitud:'
1703
1695
  too_many_marks: Estàs fent servir massa signes de puntuació consecutius (p. ex. i?)
1704
1696
  too_much_caps: Estàs utilitzant massa lletres majúscules (més del 25% del text)
1705
- too_short: És massa curt (menys de 15 caràcters)
1697
+ too_short: És massa curt (menys %{count} caràcters)
1706
1698
  forms:
1707
1699
  correct_errors: Hi ha errors al formulari, si us plau corregeix-los per continuar.
1708
1700
  length_validator: