active_storage_validations 1.4.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|