active_storage_validations 1.4.0 → 2.0.1
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.
- checksums.yaml +4 -4
- data/README.md +619 -213
- data/config/locales/da.yml +50 -30
- data/config/locales/de.yml +50 -30
- data/config/locales/en.yml +50 -30
- data/config/locales/es.yml +50 -30
- data/config/locales/fr.yml +50 -30
- data/config/locales/it.yml +50 -30
- data/config/locales/ja.yml +50 -30
- data/config/locales/nl.yml +50 -30
- data/config/locales/pl.yml +50 -30
- data/config/locales/pt-BR.yml +50 -30
- data/config/locales/ru.yml +50 -30
- data/config/locales/sv.yml +50 -30
- data/config/locales/tr.yml +50 -30
- data/config/locales/uk.yml +50 -30
- data/config/locales/vi.yml +50 -30
- data/config/locales/zh-CN.yml +50 -30
- data/lib/active_storage_validations/analyzer/audio_analyzer.rb +58 -0
- data/lib/active_storage_validations/analyzer/content_type_analyzer.rb +60 -0
- data/lib/active_storage_validations/analyzer/image_analyzer/image_magick.rb +4 -4
- data/lib/active_storage_validations/analyzer/image_analyzer/vips.rb +11 -12
- data/lib/active_storage_validations/analyzer/image_analyzer.rb +9 -53
- data/lib/active_storage_validations/analyzer/null_analyzer.rb +2 -2
- data/lib/active_storage_validations/analyzer/shared/asv_ff_probable.rb +61 -0
- data/lib/active_storage_validations/analyzer/video_analyzer.rb +130 -0
- data/lib/active_storage_validations/analyzer.rb +54 -1
- data/lib/active_storage_validations/aspect_ratio_validator.rb +15 -11
- data/lib/active_storage_validations/{base_size_validator.rb → base_comparison_validator.rb} +18 -16
- data/lib/active_storage_validations/content_type_validator.rb +56 -23
- data/lib/active_storage_validations/dimension_validator.rb +20 -19
- data/lib/active_storage_validations/duration_validator.rb +55 -0
- data/lib/active_storage_validations/extensors/asv_blob_metadatable.rb +49 -0
- data/lib/active_storage_validations/{marcel_extensor.rb → extensors/asv_marcelable.rb} +3 -0
- data/lib/active_storage_validations/limit_validator.rb +14 -2
- data/lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb +1 -1
- data/lib/active_storage_validations/matchers/{base_size_validator_matcher.rb → base_comparison_validator_matcher.rb} +31 -25
- data/lib/active_storage_validations/matchers/content_type_validator_matcher.rb +7 -3
- data/lib/active_storage_validations/matchers/dimension_validator_matcher.rb +1 -1
- data/lib/active_storage_validations/matchers/duration_validator_matcher.rb +39 -0
- data/lib/active_storage_validations/matchers/{processable_image_validator_matcher.rb → processable_file_validator_matcher.rb} +5 -5
- data/lib/active_storage_validations/matchers/size_validator_matcher.rb +18 -2
- data/lib/active_storage_validations/matchers/total_size_validator_matcher.rb +18 -2
- data/lib/active_storage_validations/matchers.rb +5 -3
- data/lib/active_storage_validations/{processable_image_validator.rb → processable_file_validator.rb} +4 -3
- data/lib/active_storage_validations/railtie.rb +5 -0
- data/lib/active_storage_validations/shared/asv_analyzable.rb +38 -3
- data/lib/active_storage_validations/shared/asv_attachable.rb +36 -15
- data/lib/active_storage_validations/size_validator.rb +11 -3
- data/lib/active_storage_validations/total_size_validator.rb +9 -3
- data/lib/active_storage_validations/version.rb +1 -1
- data/lib/active_storage_validations.rb +7 -3
- metadata +14 -8
- data/lib/active_storage_validations/content_type_spoof_detector.rb +0 -96
data/config/locales/tr.yml
CHANGED
@@ -1,33 +1,53 @@
|
|
1
1
|
tr:
|
2
2
|
errors:
|
3
3
|
messages:
|
4
|
-
content_type_invalid:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
4
|
+
content_type_invalid:
|
5
|
+
one: "geçersiz içerik türüne sahip (yetkili içerik türü %{authorized_human_content_types})"
|
6
|
+
other: "geçersiz içerik türüne sahip (yetkili içerik türleri %{authorized_human_content_types})"
|
7
|
+
content_type_spoofed:
|
8
|
+
one: "içeriği aracılığıyla algılanan içerik türüne eşdeğer olmayan bir içerik türüne sahiptir (yetkili içerik türü %{authorized_human_content_types})"
|
9
|
+
other: "içeriği aracılığıyla algılanan içerik türüne eşdeğer olmayan bir içerik türüne sahiptir (yetkili içerik türleri %{authorized_human_content_types})"
|
10
|
+
file_size_not_less_than: "dosya boyutu %{max} boyutundan küçük olmalıdır (geçerli boyut %{file_size}'dir)"
|
11
|
+
file_size_not_less_than_or_equal_to: "dosya boyutu %{max} değerinden küçük veya ona eşit olmalıdır (geçerli boyut %{file_size}'dir)"
|
12
|
+
file_size_not_greater_than: "dosya boyutu %{min} boyutundan büyük olmalıdır (geçerli boyut %{file_size}'dir)"
|
13
|
+
file_size_not_greater_than_or_equal_to: "dosya boyutu %{min} değerinden büyük veya eşit olmalıdır (geçerli boyut %{file_size}'dir)"
|
14
|
+
file_size_not_between: "dosya boyutu %{min} ile %{max} arasında olmalıdır (geçerli boyut %{file_size}'dir)"
|
15
|
+
total_file_size_not_less_than: "toplam dosya boyutu %{max} boyutundan küçük olmalıdır (geçerli boyut %{total_file_size}'dir)"
|
16
|
+
total_file_size_not_less_than_or_equal_to: "toplam dosya boyutu %{max} değerinden küçük veya ona eşit olmalıdır (geçerli boyut %{total_file_size}'dir)"
|
17
|
+
total_file_size_not_greater_than: "toplam dosya boyutu %{min} boyutundan büyük olmalıdır (geçerli boyut %{total_file_size}'dir)"
|
18
|
+
total_file_size_not_greater_than_or_equal_to: "toplam dosya boyutu %{min} değerinden büyük veya eşit olmalıdır (geçerli boyut %{total_file_size}'dir)"
|
19
|
+
total_file_size_not_between: "toplam dosya boyutu %{min} ile %{max} arasında olmalıdır (geçerli boyut %{total_file_size}'dir)"
|
20
|
+
duration_not_less_than: "süre %{max} değerinden az olmalıdır (geçerli süre %{duration})"
|
21
|
+
duration_not_less_than_or_equal_to: "süre %{max} değerine eşit veya daha düşük olmalıdır (geçerli süre %{duration})"
|
22
|
+
duration_not_greater_than: "süre %{min} değerinden büyük olmalıdır (geçerli süre %{duration})"
|
23
|
+
duration_not_greater_than_or_equal_to: "süre %{min} değerine eşit veya daha büyük olmalıdır (geçerli süre %{duration})"
|
24
|
+
duration_not_between: "süre %{min} ile %{max} arasında olmalıdır (geçerli süre %{duration})"
|
25
|
+
limit_out_of_range:
|
26
|
+
zero: "dosya eklenmedi ( %{min} ve %{max} dosyaları arasında olmalıdır)"
|
27
|
+
one: "yalnızca 1 dosya eklenmiş ( %{min} ve %{max} dosyaları arasında olmalıdır)"
|
28
|
+
other: "toplam dosya sayısı %{min} ve %{max} dosyaları arasında olmalıdır ( %{count} dosyaları ektedir)"
|
29
|
+
limit_min_not_reached:
|
30
|
+
zero: "dosya eklenmedi (en az %{min} dosyaları olmalıdır)"
|
31
|
+
one: "yalnızca 1 dosya eklenmiş (en az %{min} dosyalarına sahip olmalıdır)"
|
32
|
+
other: "%{count} dosyaları eklenmiş (en az %{min} dosyaları olmalıdır)"
|
33
|
+
limit_max_exceeded:
|
34
|
+
zero: "dosya eklenmedi (maksimum %{max} dosyaları)"
|
35
|
+
one: "çok fazla dosya eklendi (maksimum %{max} dosyaları, %{count})"
|
36
|
+
other: "çok fazla dosya eklendi (maksimum %{max} dosyaları, %{count} var)"
|
37
|
+
media_metadata_missing: "geçerli bir medya dosyası değil"
|
38
|
+
dimension_min_not_included_in: "%{width} x %{height} piksele eşit ya da büyük olmalı"
|
39
|
+
dimension_max_not_included_in: "%{width} x %{height} piksele eşit ya da küçük olmalı"
|
40
|
+
dimension_width_not_included_in: "en %{min} ve %{max} piksel aralığı dışında"
|
41
|
+
dimension_height_not_included_in: "boy %{min} ve %{max} piksel aralığı dışında"
|
42
|
+
dimension_width_not_greater_than_or_equal_to: "en %{length} piksele eşit ya da büyük olmalı"
|
43
|
+
dimension_height_not_greater_than_or_equal_to: "boy %{length} piksele eşit ya da büyük olmalı"
|
44
|
+
dimension_width_not_less_than_or_equal_to: "en %{length} piksele eşit ya da küçük olmalı"
|
45
|
+
dimension_height_not_less_than_or_equal_to: "boy %{length} piksele eşit ya da küçük olmalı"
|
46
|
+
dimension_width_not_equal_to: "en %{length} piksele eşit olmalı"
|
47
|
+
dimension_height_not_equal_to: "boy %{length} piksele eşit olmalı"
|
48
|
+
aspect_ratio_not_square: "kare olmalı (geçerli dosya %{width}x%{height}px)"
|
49
|
+
aspect_ratio_not_portrait: "portre olmalı (geçerli dosya %{width}x%{height}px)"
|
50
|
+
aspect_ratio_not_landscape: "yatay olmalıdır (geçerli dosya %{width}x%{height}px)"
|
51
|
+
aspect_ratio_not_x_y: "%{authorized_aspect_ratios} olmalıdır (geçerli dosya %{width}x%{height}px)"
|
52
|
+
aspect_ratio_invalid: "geçersiz bir en boy oranına sahiptir (geçerli en boy oranları %{authorized_aspect_ratios})"
|
53
|
+
file_not_processable: "geçerli bir medya dosyası olarak tanımlanmadı"
|
data/config/locales/uk.yml
CHANGED
@@ -1,33 +1,53 @@
|
|
1
1
|
uk:
|
2
2
|
errors:
|
3
3
|
messages:
|
4
|
-
content_type_invalid:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
4
|
+
content_type_invalid:
|
5
|
+
one: "має недійсний тип вмісту (уповноважений тип вмісту становить %{autorized_human_content_types})"
|
6
|
+
other: "має недійсний тип вмісту (дозволені типи вмісту %{autorized_human_content_types})"
|
7
|
+
content_type_spoofed:
|
8
|
+
one: "має тип вмісту, який не еквівалентний тому, який виявляється через його вміст (уповноважений тип вмісту становить %{autorized_human_content_types})"
|
9
|
+
other: "має тип вмісту, який не еквівалентний тому, який виявляється через його вміст (дозволені типи вмісту %{autorized_human_content_types})"
|
10
|
+
file_size_not_less_than: "розмір файлу має бути менше %{max} (поточний розмір %{file_size})"
|
11
|
+
file_size_not_less_than_or_equal_to: "розмір файлу має бути меншим або дорівнювати %{max} (поточний розмір %{file_size})"
|
12
|
+
file_size_not_greater_than: "розмір файлу має бути більшим ніж %{min} (поточний розмір %{file_size})"
|
13
|
+
file_size_not_greater_than_or_equal_to: "розмір файлу має бути більшим або дорівнювати %{min} (поточний розмір %{file_size})"
|
14
|
+
file_size_not_between: "розмір файлу має бути від %{min} до %{max} (поточний розмір %{file_size})"
|
15
|
+
total_file_size_not_less_than: "загальний розмір файлу має бути менше %{max} (поточний розмір %{total_file_size})"
|
16
|
+
total_file_size_not_less_than_or_equal_to: "загальний розмір файлу має бути меншим або дорівнювати %{max} (поточний розмір %{total_file_size})"
|
17
|
+
total_file_size_not_greater_than: "загальний розмір файлу має бути більшим ніж %{min} (поточний розмір %{total_file_size})"
|
18
|
+
total_file_size_not_greater_than_or_equal_to: "загальний розмір файлу має бути більшим або дорівнювати %{min} (поточний розмір %{total_file_size})"
|
19
|
+
total_file_size_not_between: "загальний розмір файлу має бути від %{min} до %{max} (поточний розмір %{total_file_size})"
|
20
|
+
duration_not_less_than: "тривалість повинна бути меншою ніж %{max} (поточна тривалість становить %{duration})"
|
21
|
+
duration_not_less_than_or_equal_to: "тривалість повинна бути меншою або дорівнює %{max} (поточна тривалість становить %{duration})"
|
22
|
+
duration_not_greater_than: "тривалість повинна бути більше %{min} (поточна тривалість становить %{duration})"
|
23
|
+
duration_not_greater_than_or_equal_to: "тривалість повинна бути більшою або дорівнює %{min} (поточна тривалість становить %{duration})"
|
24
|
+
duration_not_between: "тривалість повинна бути між %{min} і %{max} (поточна тривалість становить %{duration})"
|
25
|
+
limit_out_of_range:
|
26
|
+
zero: "немає доданих файлів (повинно мати між %{min} і %{max} файли)"
|
27
|
+
one: "додається лише 1 файл (повинен мати між %{min} і %{max} файли)"
|
28
|
+
other: "загальна кількість файлів повинна бути між %{min} і %{max} файлами (є %{count} файли)"
|
29
|
+
limit_min_not_reached:
|
30
|
+
zero: "немає доданих файлів (повинен мати принаймні %{min} файлів)"
|
31
|
+
one: "додається лише 1 файл (повинен мати принаймні %{min} файли)"
|
32
|
+
other: "%{count} додані файли (повинні мати принаймні %{min} файли)"
|
33
|
+
limit_max_exceeded:
|
34
|
+
zero: "не додано файлів (максимум -%{max} файли)"
|
35
|
+
one: "занадто багато доданих файлів (максимум -%{max} файлів, отримав %{count})"
|
36
|
+
other: "занадто багато доданих файлів (максимум -%{max} файлів, отримав %{count})"
|
37
|
+
media_metadata_missing: "не є допустимим зображенням"
|
38
|
+
dimension_min_not_included_in: "мусить бути більше або дорівнювати %{width} x %{height} пікселям"
|
39
|
+
dimension_max_not_included_in: "мусить бути менше або дорівнювати %{width} x %{height} пікселям"
|
40
|
+
dimension_width_not_included_in: "ширина не включена між %{min} і %{max} пікселям"
|
41
|
+
dimension_height_not_included_in: "висота не включена між %{min} і %{max} пікселям"
|
42
|
+
dimension_width_not_greater_than_or_equal_to: "ширина мусить бути більше або дорівнювати %{length} пікселям"
|
43
|
+
dimension_height_not_greater_than_or_equal_to: "висота мусить бути більше або дорівнювати %{length} пікселям"
|
44
|
+
dimension_width_not_less_than_or_equal_to: "ширина мусить бути менше або дорівнювати %{length} пікселям"
|
45
|
+
dimension_height_not_less_than_or_equal_to: "висота мусить бути менше або дорівнювати %{length} пікселям"
|
46
|
+
dimension_width_not_equal_to: "ширина мусить дорівнювати %{length} пікселям"
|
47
|
+
dimension_height_not_equal_to: "висота мусить дорівнювати %{length} пікселям"
|
48
|
+
aspect_ratio_not_square: "повинен бути квадратним (поточний файл %{width}x%{height} пікселям)"
|
49
|
+
aspect_ratio_not_portrait: "повинен бути портретним (поточний файл %{width}x%{height} пікселям)"
|
50
|
+
aspect_ratio_not_landscape: "повинен бути пейзажним (поточний файл %{width}x%{height} пікселям)"
|
51
|
+
aspect_ratio_not_x_y: "повинен бути %{authorized_aspect_ratios} (поточний файл становить %{width}x%{height} пікселям)"
|
52
|
+
aspect_ratio_invalid: "має недійсне співвідношення сторін (дійсні співвідношення сторін %{authorized_aspect_ratios})"
|
53
|
+
file_not_processable: "не ідентифікується як дійсний медіа-файл"
|
data/config/locales/vi.yml
CHANGED
@@ -1,33 +1,53 @@
|
|
1
1
|
vi:
|
2
2
|
errors:
|
3
3
|
messages:
|
4
|
-
content_type_invalid:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
4
|
+
content_type_invalid:
|
5
|
+
one: "có loại nội dung không hợp lệ (loại nội dung được ủy quyền là %{autorized_human_content_types})"
|
6
|
+
other: "có loại nội dung không hợp lệ (các loại nội dung được ủy quyền là %{autorized_human_content_types})"
|
7
|
+
content_type_spoofed:
|
8
|
+
one: "có một loại nội dung không tương đương với loại được phát hiện thông qua nội dung của nó (loại nội dung được ủy quyền là %{autorized_human_content_types})"
|
9
|
+
other: "có một loại nội dung không tương đương với loại được phát hiện thông qua nội dung của nó (các loại nội dung được ủy quyền là %{autorized_human_content_types})"
|
10
|
+
file_size_not_less_than: "kích thước tệp phải nhỏ hơn %{max} (kích thước hiện tại là %{file_size})"
|
11
|
+
file_size_not_less_than_or_equal_to: "kích thước tệp phải nhỏ hơn hoặc bằng %{max} (kích thước hiện tại là %{file_size})"
|
12
|
+
file_size_not_greater_than: "kích thước tệp phải lớn hơn %{min} (kích thước hiện tại là %{file_size})"
|
13
|
+
file_size_not_greater_than_or_equal_to: "kích thước tệp phải lớn hơn hoặc bằng %{min} (kích thước hiện tại là %{file_size})"
|
14
|
+
file_size_not_between: "kích thước tệp phải nằm trong khoảng từ %{min} đến %{max} (kích thước hiện tại là %{file_size})"
|
15
|
+
total_file_size_not_less_than: "tổng kích thước tệp phải nhỏ hơn %{max} (kích thước hiện tại là %{total_file_size})"
|
16
|
+
total_file_size_not_less_than_or_equal_to: "tổng kích thước tệp phải nhỏ hơn hoặc bằng %{max} (kích thước hiện tại là %{total_file_size})"
|
17
|
+
total_file_size_not_greater_than: "tổng kích thước tệp phải lớn hơn %{min} (kích thước hiện tại là %{total_file_size})"
|
18
|
+
total_file_size_not_greater_than_or_equal_to: "tổng kích thước tệp phải lớn hơn hoặc bằng %{min} (kích thước hiện tại là %{total_file_size})"
|
19
|
+
total_file_size_not_between: "tổng kích thước tệp phải nằm trong khoảng từ %{min} đến %{max} (kích thước hiện tại là %{total_file_size})"
|
20
|
+
duration_not_less_than: "thời lượng phải nhỏ hơn %{max} (thời lượng hiện tại là %{duration})"
|
21
|
+
duration_not_less_than_or_equal_to: "thời lượng phải nhỏ hơn hoặc bằng %{max} (thời lượng hiện tại là %{duration})"
|
22
|
+
duration_not_greater_than: "thời lượng phải lớn hơn %{min} (thời lượng hiện tại là %{duration})"
|
23
|
+
duration_not_greater_than_or_equal_to: "thời lượng phải lớn hơn hoặc bằng %{min} (thời lượng hiện tại là %{duration})"
|
24
|
+
duration_not_between: "thời lượng phải nằm trong khoảng từ %{min} và %{max} (thời lượng hiện tại là %{duration})"
|
25
|
+
limit_out_of_range:
|
26
|
+
zero: "không có tệp nào được đính kèm (phải có giữa các tệp %{min} và %{max})"
|
27
|
+
one: "chỉ có 1 tệp được đính kèm (phải có giữa các tệp %{min} và %{max})"
|
28
|
+
other: "tổng số tệp phải nằm trong khoảng từ %{min} và %{max} tệp (có các tệp %{count} được đính kèm)"
|
29
|
+
limit_min_not_reached:
|
30
|
+
zero: "không có tệp nào được đính kèm (phải có ít nhất %{min} tệp)"
|
31
|
+
one: "chỉ có 1 tệp được đính kèm (phải có ít nhất %{min} tệp)"
|
32
|
+
other: "các tệp %{count} được đính kèm (phải có ít nhất %{min} tệp)"
|
33
|
+
limit_max_exceeded:
|
34
|
+
zero: "không có tệp nào được đính kèm (tối đa là các tệp %{max})"
|
35
|
+
one: "quá nhiều tệp được đính kèm (tối đa là các tệp %{max}, có %{count})"
|
36
|
+
other: "quá nhiều tệp được đính kèm (tối đa là các tệp %{max}, có %{count})"
|
37
|
+
media_metadata_missing: "không phải là ảnh"
|
38
|
+
dimension_min_not_included_in: "phải lớn hơn hoặc bằng %{width} x %{height} pixel"
|
39
|
+
dimension_max_not_included_in: "phải nhỏ hơn hoặc bằng %{width} x %{height} pixel"
|
40
|
+
dimension_width_not_included_in: "chiều rộng không nằm trong %{min} và %{max} pixel"
|
41
|
+
dimension_height_not_included_in: "chiều cao không nằm trong %{min} và %{max} pixel"
|
42
|
+
dimension_width_not_greater_than_or_equal_to: "chiều rộng phải lớn hơn hoặc bằng %{length} pixel"
|
43
|
+
dimension_height_not_greater_than_or_equal_to: "chiều cao phải lớn hơn hoặc bằng %{length} pixel"
|
44
|
+
dimension_width_not_less_than_or_equal_to: "chiều rộng phải nhỏ hơn hoặc bằng %{length} pixel"
|
45
|
+
dimension_height_not_less_than_or_equal_to: "chiều cao phải nhỏ hơn hoặc bằng %{length} pixel"
|
46
|
+
dimension_width_not_equal_to: "chiều rộng phải bằng %{length} pixel"
|
47
|
+
dimension_height_not_equal_to: "chiều cao phải bằng %{length} pixel"
|
48
|
+
aspect_ratio_not_square: "phải là hình vuông (tệp hiện tại là %{width}x%{height}px)"
|
49
|
+
aspect_ratio_not_portrait: "phải là chân dung (tệp hiện tại là %{width}x%{height}px)"
|
50
|
+
aspect_ratio_not_landscape: "phải là ngang (tệp hiện tại là %{width}x%{height}px)"
|
51
|
+
aspect_ratio_not_x_y: "phải là %{authorized_aspect_ratios} (tệp hiện tại là %{width}x%{height}px)"
|
52
|
+
aspect_ratio_invalid: "có tỷ lệ khung hình không hợp lệ (tỷ lệ khung hình hợp lệ là %{authorized_aspect_ratios})"
|
53
|
+
file_not_processable: "không được xác định là tệp phương tiện hợp lệ"
|
data/config/locales/zh-CN.yml
CHANGED
@@ -1,33 +1,53 @@
|
|
1
1
|
zh-CN:
|
2
2
|
errors:
|
3
3
|
messages:
|
4
|
-
content_type_invalid:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
4
|
+
content_type_invalid:
|
5
|
+
one: "具有无效的内容类型(授权的内容类型为%{authorized_human_content_types})"
|
6
|
+
other: "具有无效的内容类型(授权的内容类型为%{authorized_human_content_types})"
|
7
|
+
content_type_spoofed:
|
8
|
+
one: "其内容类型不等于通过其内容检测到的内容类型(授权内容类型为%{authorized_human_content_types})"
|
9
|
+
other: "其内容类型与通过其内容检测到的内容类型不等效(授权内容类型为%{authorized_human_content_types})"
|
10
|
+
file_size_not_less_than: "文件大小必须小于 %{max}(当前大小为 %{file_size})"
|
11
|
+
file_size_not_less_than_or_equal_to: "文件大小必须小于或等于 %{max}(当前大小为 %{file_size})"
|
12
|
+
file_size_not_greater_than: "文件大小必须大于 %{min}(当前大小为 %{file_size})"
|
13
|
+
file_size_not_greater_than_or_equal_to: "文件大小必须大于或等于 %{min}(当前大小为 %{file_size})"
|
14
|
+
file_size_not_between: "文件大小必须介于 %{min} 和 %{max} 之间(当前大小为 %{file_size})"
|
15
|
+
total_file_size_not_less_than: "总文件大小必须小于 %{max}(当前大小为 %{total_file_size})"
|
16
|
+
total_file_size_not_less_than_or_equal_to: "文件总大小必须小于或等于 %{max}(当前大小为 %{total_file_size})"
|
17
|
+
total_file_size_not_greater_than: "总文件大小必须大于 %{min}(当前大小为 %{total_file_size})"
|
18
|
+
total_file_size_not_greater_than_or_equal_to: "文件总大小必须大于或等于 %{min}(当前大小为 %{total_file_size})"
|
19
|
+
total_file_size_not_between: "总文件大小必须介于 %{min} 和 %{max} 之间(当前大小为 %{total_file_size})"
|
20
|
+
duration_not_less_than: "持续时间必须小于%{max}(当前持续时间为%{duration})"
|
21
|
+
duration_not_less_than_or_equal_to: "持续时间必须小于或等于%{max}(当前持续时间为%{duration})"
|
22
|
+
duration_not_greater_than: "持续时间必须大于%{min}(当前持续时间为%{duration})"
|
23
|
+
duration_not_greater_than_or_equal_to: "持续时间必须大于或等于%{min}(当前持续时间为%{duration})"
|
24
|
+
duration_not_between: "持续时间必须在%{min}和%{max}之间(当前持续时间为%{duration})"
|
25
|
+
limit_out_of_range:
|
26
|
+
zero: "未附加文件(必须具有%{min}和%{max}文件之间)"
|
27
|
+
one: "仅附加1个文件(必须具有%{min}和%{max}文件之间)"
|
28
|
+
other: "文件总数必须在%{min}和%{max}文件之间(已连接%{count}文件)"
|
29
|
+
limit_min_not_reached:
|
30
|
+
zero: "未附加文件(必须至少具有%{min}文件)"
|
31
|
+
one: "仅附加1个文件(必须至少具有%{min}文件)"
|
32
|
+
other: "%{count}文件已连接(必须至少具有%{min}文件)"
|
33
|
+
limit_max_exceeded:
|
34
|
+
zero: "未附加文件(最大为%{max}文件)"
|
35
|
+
one: "附加的文件太多(最大为%{max}文件,得到%{count})"
|
36
|
+
other: "附加的文件太多(最大为%{max}文件,得到%{count})"
|
37
|
+
media_metadata_missing: "不是有效的媒体文件"
|
38
|
+
dimension_min_not_included_in: "必须大于或等于 %{width} x %{height} 像素"
|
39
|
+
dimension_max_not_included_in: "必须小于或等于 %{width} x %{height} 像素"
|
40
|
+
dimension_width_not_included_in: "宽度不在 %{min} 和 %{max} 像素之间"
|
41
|
+
dimension_height_not_included_in: "高度不在 %{min} 和 %{max} 像素之间"
|
42
|
+
dimension_width_not_greater_than_or_equal_to: "宽度必须大于或等于 %{length} 像素"
|
43
|
+
dimension_height_not_greater_than_or_equal_to: "高度必须大于或等于 %{length} 像素"
|
44
|
+
dimension_width_not_less_than_or_equal_to: "宽度必须小于或等于 %{length} 像素"
|
45
|
+
dimension_height_not_less_than_or_equal_to: "高度必须小于或等于 %{length} 像素"
|
46
|
+
dimension_width_not_equal_to: "宽度必须等于 %{length} 像素"
|
47
|
+
dimension_height_not_equal_to: "高度必须等于 %{length} 像素"
|
48
|
+
aspect_ratio_not_square: "必须为正方形(当前文件为 %{width} x%{height} 像素)"
|
49
|
+
aspect_ratio_not_portrait: "必须是纵向的(当前文件为 %{width} x%{height} 像素)"
|
50
|
+
aspect_ratio_not_landscape: "必须是横向(当前文件为 %{width} x%{height} 像素)"
|
51
|
+
expect_ratio_not_x_y: "必须为 %{authorized_aspect_ratios}(当前文件为 %{width} x%{height} 像素)"
|
52
|
+
expect_ratio_not_in_list: "具有无效的长宽比(有效长宽比为 %{authorized_aspect_ratios})"
|
53
|
+
file_not_processable: "未标识为有效的媒体文件"
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
require_relative 'shared/asv_ff_probable'
|
5
|
+
|
6
|
+
module ActiveStorageValidations
|
7
|
+
# = ActiveStorageValidations Audio \Analyzer
|
8
|
+
#
|
9
|
+
# Extracts the following from an audio attachable:
|
10
|
+
#
|
11
|
+
# * Duration (seconds)
|
12
|
+
# * Bit rate (bits/s)
|
13
|
+
# * Sample rate (hertz)
|
14
|
+
# * Tags (internal metadata)
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
#
|
18
|
+
# ActiveStorageValidations::Analyzer::AudioAnalyzer.new(attachable).metadata
|
19
|
+
# # => { duration: 5.0, bit_rate: 320340, sample_rate: 44100, tags: { encoder: "Lavc57.64", ... } }
|
20
|
+
#
|
21
|
+
# This analyzer requires the {FFmpeg}[https://www.ffmpeg.org] system library, which is not provided by \Rails.
|
22
|
+
class Analyzer::AudioAnalyzer < Analyzer
|
23
|
+
include ASVFFProbable
|
24
|
+
|
25
|
+
def metadata
|
26
|
+
read_media do |media|
|
27
|
+
{
|
28
|
+
duration: duration,
|
29
|
+
bit_rate: bit_rate,
|
30
|
+
sample_rate: sample_rate,
|
31
|
+
tags: tags
|
32
|
+
}.compact
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def duration
|
39
|
+
duration = audio_stream["duration"]
|
40
|
+
Float(duration).round(1) if duration
|
41
|
+
end
|
42
|
+
|
43
|
+
def bit_rate
|
44
|
+
bit_rate = audio_stream["bit_rate"]
|
45
|
+
Integer(bit_rate) if bit_rate
|
46
|
+
end
|
47
|
+
|
48
|
+
def sample_rate
|
49
|
+
sample_rate = audio_stream["sample_rate"]
|
50
|
+
Integer(sample_rate) if sample_rate
|
51
|
+
end
|
52
|
+
|
53
|
+
def tags
|
54
|
+
tags = audio_stream["tags"]
|
55
|
+
Hash(tags) if tags
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
module ActiveStorageValidations
|
6
|
+
# = ActiveStorageValidations ContentType \Analyzer
|
7
|
+
#
|
8
|
+
# Extracts the content type from an attachable. This is used to prevent content
|
9
|
+
# type spoofing.
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
#
|
13
|
+
# ActiveStorageValidations::Analyzer::ContentTypeAnalyzer.new(attachable).content_type
|
14
|
+
# # => { content_type: "image/png" }
|
15
|
+
#
|
16
|
+
# This analyzer requires the {UNIX file}[https://en.wikipedia.org/wiki/File_(command)] command, which is not provided by \Rails. While it is available on most UNIX distributions, it may need to be installed explicitly on minimal or custom setups.
|
17
|
+
class Analyzer::ContentTypeAnalyzer < Analyzer
|
18
|
+
class FileCommandLineToolNotInstalledError < StandardError; end
|
19
|
+
|
20
|
+
def content_type
|
21
|
+
read_media do |media|
|
22
|
+
{
|
23
|
+
content_type: media
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def read_media
|
31
|
+
Tempfile.create(binmode: true) do |tempfile|
|
32
|
+
begin
|
33
|
+
if media(tempfile).present?
|
34
|
+
yield media(tempfile)
|
35
|
+
else
|
36
|
+
logger.info "Skipping file content_type analysis because Linux file command doesn't support the file"
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
ensure
|
40
|
+
tempfile.close
|
41
|
+
end
|
42
|
+
end
|
43
|
+
rescue Errno::ENOENT
|
44
|
+
raise FileCommandLineToolNotInstalledError, 'file command-line tool is not installed'
|
45
|
+
end
|
46
|
+
|
47
|
+
def media_from_path(path)
|
48
|
+
instrument("file") do
|
49
|
+
stdout, status = Open3.capture2(
|
50
|
+
'file',
|
51
|
+
'-b',
|
52
|
+
'--mime-type',
|
53
|
+
path
|
54
|
+
)
|
55
|
+
|
56
|
+
status.success? ? stdout.strip : nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -8,11 +8,11 @@ module ActiveStorageValidations
|
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
def
|
11
|
+
def read_media
|
12
12
|
Tempfile.create(binmode: true) do |tempfile|
|
13
13
|
begin
|
14
|
-
if
|
15
|
-
yield
|
14
|
+
if media(tempfile).valid?
|
15
|
+
yield media(tempfile)
|
16
16
|
else
|
17
17
|
logger.info "Skipping image analysis because ImageMagick doesn't support the file"
|
18
18
|
{}
|
@@ -26,7 +26,7 @@ module ActiveStorageValidations
|
|
26
26
|
{}
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
29
|
+
def media_from_path(path)
|
30
30
|
instrument("mini_magick") do
|
31
31
|
MiniMagick::Image.new(path)
|
32
32
|
end
|
@@ -7,11 +7,11 @@ module ActiveStorageValidations
|
|
7
7
|
|
8
8
|
private
|
9
9
|
|
10
|
-
def
|
10
|
+
def read_media
|
11
11
|
Tempfile.create(binmode: true) do |tempfile|
|
12
12
|
begin
|
13
|
-
if
|
14
|
-
yield
|
13
|
+
if media(tempfile)
|
14
|
+
yield media(tempfile)
|
15
15
|
else
|
16
16
|
logger.info "Skipping image analysis because Vips doesn't support the file"
|
17
17
|
{}
|
@@ -25,7 +25,7 @@ module ActiveStorageValidations
|
|
25
25
|
{}
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
28
|
+
def media_from_path(path)
|
29
29
|
instrument("vips") do
|
30
30
|
begin
|
31
31
|
::Vips::Image.new_from_file(path, access: :sequential)
|
@@ -34,12 +34,18 @@ module ActiveStorageValidations
|
|
34
34
|
# supported attachable.
|
35
35
|
# We stumbled upon this issue while reading 0 byte size attachable
|
36
36
|
# https://github.com/janko/image_processing/issues/97
|
37
|
-
logger.info "Skipping image analysis because Vips doesn't support the file"
|
38
37
|
nil
|
39
38
|
end
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
42
|
+
ROTATIONS = /Right-top|Left-bottom|Top-right|Bottom-left/
|
43
|
+
def rotated_image?(image)
|
44
|
+
ROTATIONS === image.get("exif-ifd0-Orientation")
|
45
|
+
rescue ::Vips::Error
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
43
49
|
def supported?
|
44
50
|
require "vips"
|
45
51
|
true
|
@@ -47,12 +53,5 @@ module ActiveStorageValidations
|
|
47
53
|
logger.info "Skipping image analysis because the ruby-vips gem isn't installed"
|
48
54
|
false
|
49
55
|
end
|
50
|
-
|
51
|
-
ROTATIONS = /Right-top|Left-bottom|Top-right|Bottom-left/
|
52
|
-
def rotated_image?(image)
|
53
|
-
ROTATIONS === image.get("exif-ifd0-Orientation")
|
54
|
-
rescue ::Vips::Error
|
55
|
-
false
|
56
|
-
end
|
57
56
|
end
|
58
57
|
end
|