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.
- checksums.yaml +4 -4
- data/app/cells/decidim/amendable/announcement_cell.rb +1 -1
- data/app/cells/decidim/card_m_cell.rb +1 -1
- data/app/controllers/decidim/devise/invitations_controller.rb +9 -2
- data/app/controllers/decidim/last_activities_controller.rb +5 -2
- data/app/forms/decidim/account_form.rb +2 -2
- data/app/forms/decidim/amendable/form.rb +2 -1
- data/app/forms/decidim/registration_form.rb +2 -2
- data/app/forms/decidim/upload_validation_form.rb +51 -7
- data/app/helpers/decidim/layout_helper.rb +12 -4
- data/app/helpers/decidim/sanitize_helper.rb +1 -1
- data/app/mailers/decidim/notification_mailer.rb +1 -0
- data/app/mailers/decidim/notifications_digest_mailer.rb +1 -0
- data/app/packs/src/decidim/editor/clipboard_override.js +143 -0
- data/app/packs/src/decidim/editor/clipboard_utilities.js +119 -0
- data/app/packs/src/decidim/editor/linebreak_module.js +0 -8
- data/app/packs/src/decidim/editor.js +9 -2
- data/app/packs/stylesheets/decidim/_editor.scss +129 -0
- data/app/packs/stylesheets/decidim/extras/_quill.scss +0 -6
- data/app/presenters/decidim/home_stats_presenter.rb +11 -4
- data/app/presenters/decidim/stats_presenter.rb +7 -8
- data/app/presenters/decidim/user_presenter.rb +9 -4
- data/app/queries/decidim/public_activities.rb +1 -0
- data/app/validators/etiquette_validator.rb +7 -3
- data/app/validators/file_content_type_validator.rb +103 -0
- data/app/validators/passthru_validator.rb +11 -0
- data/app/validators/uploader_content_type_validator.rb +22 -0
- data/app/views/decidim/notification_mailer/event_received.html.erb +1 -1
- data/app/views/decidim/notifications_digest_mailer/_email_content.html.erb +1 -1
- data/config/locales/ar.yml +0 -15
- data/config/locales/bg.yml +1 -14
- data/config/locales/ca.yml +7 -15
- data/config/locales/cs.yml +14 -22
- data/config/locales/de.yml +1 -14
- data/config/locales/el.yml +0 -13
- data/config/locales/en.yml +5 -13
- data/config/locales/es-MX.yml +6 -14
- data/config/locales/es-PY.yml +6 -14
- data/config/locales/es.yml +11 -19
- data/config/locales/eu.yml +7 -16
- data/config/locales/fi-plain.yml +5 -13
- data/config/locales/fi.yml +5 -13
- data/config/locales/fr-CA.yml +6 -14
- data/config/locales/fr.yml +6 -14
- data/config/locales/ga-IE.yml +1 -3
- data/config/locales/gl.yml +0 -15
- data/config/locales/gn-PY.yml +1 -0
- data/config/locales/hu.yml +21 -14
- data/config/locales/id-ID.yml +0 -15
- data/config/locales/is-IS.yml +2 -1
- data/config/locales/it.yml +2 -15
- data/config/locales/ja.yml +6 -14
- data/config/locales/lb.yml +0 -13
- data/config/locales/lo-LA.yml +1 -0
- data/config/locales/lt.yml +0 -13
- data/config/locales/lv.yml +0 -13
- data/config/locales/nl.yml +2 -15
- data/config/locales/no.yml +0 -13
- data/config/locales/oc-FR.yml +1 -0
- data/config/locales/pl.yml +1 -14
- data/config/locales/pt-BR.yml +2 -15
- data/config/locales/pt.yml +1 -14
- data/config/locales/ro-RO.yml +0 -13
- data/config/locales/ru.yml +0 -4
- data/config/locales/sk.yml +0 -16
- data/config/locales/sv.yml +0 -13
- data/config/locales/tr-TR.yml +2 -15
- data/config/locales/uk.yml +1 -2
- data/config/locales/zh-CN.yml +0 -13
- data/lib/decidim/attributes/localized_date.rb +1 -1
- data/lib/decidim/attributes/time_with_zone.rb +5 -2
- data/lib/decidim/core/engine.rb +7 -5
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/editor_shared_examples.rb +30 -0
- data/lib/decidim/core/test/shared_examples/mcell_examples.rb +17 -0
- data/lib/decidim/core/test.rb +2 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/file_validator_humanizer.rb +1 -1
- data/lib/decidim/form_builder.rb +10 -3
- data/lib/decidim/resourceable.rb +5 -4
- data/lib/decidim/settings_manifest.rb +1 -1
- metadata +16 -9
- 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
|
}
|
@@ -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
|
47
|
-
|
48
|
-
|
49
|
-
|
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.
|
21
|
-
|
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
|
-
|
26
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
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>
|
data/config/locales/ar.yml
CHANGED
@@ -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:
|
data/config/locales/bg.yml
CHANGED
@@ -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:
|
data/config/locales/ca.yml
CHANGED
@@ -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:
|
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:
|
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
|
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:
|