active_storage_validations 1.3.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +620 -279
  3. data/config/locales/da.yml +50 -29
  4. data/config/locales/de.yml +50 -29
  5. data/config/locales/en.yml +50 -29
  6. data/config/locales/es.yml +50 -29
  7. data/config/locales/fr.yml +50 -29
  8. data/config/locales/it.yml +50 -29
  9. data/config/locales/ja.yml +50 -29
  10. data/config/locales/nl.yml +50 -29
  11. data/config/locales/pl.yml +50 -29
  12. data/config/locales/pt-BR.yml +50 -29
  13. data/config/locales/ru.yml +50 -29
  14. data/config/locales/sv.yml +50 -29
  15. data/config/locales/tr.yml +50 -29
  16. data/config/locales/uk.yml +50 -29
  17. data/config/locales/vi.yml +50 -29
  18. data/config/locales/zh-CN.yml +50 -29
  19. data/lib/active_storage_validations/analyzer/audio_analyzer.rb +58 -0
  20. data/lib/active_storage_validations/analyzer/content_type_analyzer.rb +60 -0
  21. data/lib/active_storage_validations/analyzer/image_analyzer/image_magick.rb +12 -11
  22. data/lib/active_storage_validations/analyzer/image_analyzer/vips.rb +12 -12
  23. data/lib/active_storage_validations/analyzer/image_analyzer.rb +18 -46
  24. data/lib/active_storage_validations/analyzer/null_analyzer.rb +2 -2
  25. data/lib/active_storage_validations/analyzer/shared/asv_ff_probable.rb +61 -0
  26. data/lib/active_storage_validations/analyzer/video_analyzer.rb +130 -0
  27. data/lib/active_storage_validations/analyzer.rb +54 -1
  28. data/lib/active_storage_validations/aspect_ratio_validator.rb +154 -120
  29. data/lib/active_storage_validations/{base_size_validator.rb → base_comparison_validator.rb} +18 -16
  30. data/lib/active_storage_validations/content_type_validator.rb +51 -17
  31. data/lib/active_storage_validations/dimension_validator.rb +20 -19
  32. data/lib/active_storage_validations/duration_validator.rb +55 -0
  33. data/lib/active_storage_validations/extensors/asv_blob_metadatable.rb +24 -0
  34. data/lib/active_storage_validations/{marcel_extensor.rb → extensors/asv_marcelable.rb} +5 -0
  35. data/lib/active_storage_validations/limit_validator.rb +14 -2
  36. data/lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb +1 -1
  37. data/lib/active_storage_validations/matchers/{base_size_validator_matcher.rb → base_comparison_validator_matcher.rb} +31 -25
  38. data/lib/active_storage_validations/matchers/content_type_validator_matcher.rb +7 -3
  39. data/lib/active_storage_validations/matchers/dimension_validator_matcher.rb +1 -1
  40. data/lib/active_storage_validations/matchers/duration_validator_matcher.rb +39 -0
  41. data/lib/active_storage_validations/matchers/{processable_image_validator_matcher.rb → processable_file_validator_matcher.rb} +5 -5
  42. data/lib/active_storage_validations/matchers/size_validator_matcher.rb +18 -2
  43. data/lib/active_storage_validations/matchers/total_size_validator_matcher.rb +18 -2
  44. data/lib/active_storage_validations/matchers.rb +4 -3
  45. data/lib/active_storage_validations/{processable_image_validator.rb → processable_file_validator.rb} +4 -3
  46. data/lib/active_storage_validations/railtie.rb +5 -0
  47. data/lib/active_storage_validations/shared/asv_active_storageable.rb +2 -2
  48. data/lib/active_storage_validations/shared/asv_analyzable.rb +38 -3
  49. data/lib/active_storage_validations/shared/asv_attachable.rb +36 -15
  50. data/lib/active_storage_validations/size_validator.rb +11 -3
  51. data/lib/active_storage_validations/total_size_validator.rb +9 -3
  52. data/lib/active_storage_validations/version.rb +1 -1
  53. data/lib/active_storage_validations.rb +7 -3
  54. metadata +14 -8
  55. data/lib/active_storage_validations/content_type_spoof_detector.rb +0 -96
@@ -1,32 +1,53 @@
1
1
  tr:
2
2
  errors:
3
3
  messages:
4
- content_type_invalid: "geçersiz dosya tipine sahip"
5
- spoofed_content_type: "içeriği, dosya adı ve uzantısı aracılığıyla bildirildiği gibi olmayan bir içerik türüne sahip"
6
- file_size_not_less_than: "dosya boyutu %{max_size} boyutundan küçük olmalıdır (geçerli boyut %{file_size}'dir)"
7
- file_size_not_less_than_or_equal_to: "dosya boyutu %{max_size} değerinden küçük veya ona eşit olmalıdır (geçerli boyut %{file_size}'dir)"
8
- file_size_not_greater_than: "dosya boyutu %{min_size} boyutundan büyük olmalıdır (geçerli boyut %{file_size}'dir)"
9
- file_size_not_greater_than_or_equal_to: "dosya boyutu %{min_size} değerinden büyük veya eşit olmalıdır (geçerli boyut %{file_size}'dir)"
10
- file_size_not_between: "dosya boyutu %{min_size} ile %{max_size} arasında olmalıdır (geçerli boyut %{file_size}'dir)"
11
- total_file_size_not_less_than: "toplam dosya boyutu %{max_size} boyutundan küçük olmalıdır (geçerli boyut %{total_file_size}'dir)"
12
- total_file_size_not_less_than_or_equal_to: "toplam dosya boyutu %{max_size} değerinden küçük veya ona eşit olmalıdır (geçerli boyut %{total_file_size}'dir)"
13
- total_file_size_not_greater_than: "toplam dosya boyutu %{min_size} boyutundan büyük olmalıdır (geçerli boyut %{total_file_size}'dir)"
14
- total_file_size_not_greater_than_or_equal_to: "toplam dosya boyutu %{min_size} değerinden büyük veya eşit olmalıdır (geçerli boyut %{total_file_size}'dir)"
15
- total_file_size_not_between: "toplam dosya boyutu %{min_size} ile %{max_size} arasında olmalıdır (geçerli boyut %{total_file_size}'dir)"
16
- limit_out_of_range: "toplam miktar aralık dışında"
17
- image_metadata_missing: "geçerli bir imaj değil"
18
- dimension_min_inclusion: "%{width} x %{height} piksele eşit ya da büyük olmalı"
19
- dimension_max_inclusion: "%{width} x %{height} piksele eşit ya da küçük olmalı"
20
- dimension_width_inclusion: "en %{min} ve %{max} piksel aralığı dışında"
21
- dimension_height_inclusion: "boy %{min} ve %{max} piksel aralığı dışında"
22
- dimension_width_greater_than_or_equal_to: "en %{length} piksele eşit ya da büyük olmalı"
23
- dimension_height_greater_than_or_equal_to: "boy %{length} piksele eşit ya da büyük olmalı"
24
- dimension_width_less_than_or_equal_to: "en %{length} piksele eşit ya da küçük olmalı"
25
- dimension_height_less_than_or_equal_to: "boy %{length} piksele eşit ya da küçük olmalı"
26
- dimension_width_equal_to: "en %{length} piksele eşit olmalı"
27
- dimension_height_equal_to: "boy %{length} piksele eşit olmalı"
28
- aspect_ratio_not_square: "kare bir imaj olmalı"
29
- aspect_ratio_not_portrait: "dikey bir imaj olmalı"
30
- aspect_ratio_not_landscape: "yatay bir imaj olmalı"
31
- aspect_ratio_is_not: "%{aspect_ratio} en boy oranına sahip olmalı"
32
- image_not_processable: "geçerli bir imaj değil"
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ı"
@@ -1,32 +1,53 @@
1
1
  uk:
2
2
  errors:
3
3
  messages:
4
- content_type_invalid: "має неприпустимий тип вмісту"
5
- spoofed_content_type: "має тип вмісту, який не відповідає тому, що він оголошений через його вміст, назву файлу та розширення"
6
- file_size_not_less_than: "розмір файлу має бути менше %{max_size} (поточний розмір %{file_size})"
7
- file_size_not_less_than_or_equal_to: "розмір файлу має бути меншим або дорівнювати %{max_size} (поточний розмір %{file_size})"
8
- file_size_not_greater_than: "розмір файлу має бути більшим ніж %{min_size} (поточний розмір %{file_size})"
9
- file_size_not_greater_than_or_equal_to: "розмір файлу має бути більшим або дорівнювати %{min_size} (поточний розмір %{file_size})"
10
- file_size_not_between: "розмір файлу має бути від %{min_size} до %{max_size} (поточний розмір %{file_size})"
11
- total_file_size_not_less_than: "загальний розмір файлу має бути менше %{max_size} (поточний розмір %{total_file_size})"
12
- total_file_size_not_less_than_or_equal_to: "загальний розмір файлу має бути меншим або дорівнювати %{max_size} (поточний розмір %{total_file_size})"
13
- total_file_size_not_greater_than: "загальний розмір файлу має бути більшим ніж %{min_size} (поточний розмір %{total_file_size})"
14
- total_file_size_not_greater_than_or_equal_to: "загальний розмір файлу має бути більшим або дорівнювати %{min_size} (поточний розмір %{total_file_size})"
15
- total_file_size_not_between: "загальний розмір файлу має бути від %{min_size} до %{max_size} (поточний розмір %{total_file_size})"
16
- limit_out_of_range: "кількість файлів більше необхідного"
17
- image_metadata_missing: "не є допустимим зображенням"
18
- dimension_min_inclusion: "мусить бути більше або дорівнювати %{width} x %{height} пікселям"
19
- dimension_max_inclusion: "мусить бути менше або дорівнювати %{width} x %{height} пікселям"
20
- dimension_width_inclusion: "ширина не включена між %{min} і %{max} пікселям"
21
- dimension_height_inclusion: "висота не включена між %{min} і %{max} пікселям"
22
- dimension_width_greater_than_or_equal_to: "ширина мусить бути більше або дорівнювати %{length} пікселям"
23
- dimension_height_greater_than_or_equal_to: "висота мусить бути більше або дорівнювати %{length} пікселям"
24
- dimension_width_less_than_or_equal_to: "ширина мусить бути менше або дорівнювати %{length} пікселям"
25
- dimension_height_less_than_or_equal_to: "висота мусить бути менше або дорівнювати %{length} пікселям"
26
- dimension_width_equal_to: "ширина мусить дорівнювати %{length} пікселям"
27
- dimension_height_equal_to: "висота мусить дорівнювати %{length} пікселям"
28
- aspect_ratio_not_square: "мусить бути квадратне зображення"
29
- aspect_ratio_not_portrait: "мусить бути портретне зображення"
30
- aspect_ratio_not_landscape: "мусить бути пейзажне зображення"
31
- aspect_ratio_is_not: "мусить мати співвідношення сторін %{aspect_ratio}"
32
- image_not_processable: "не є допустимим зображенням"
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: "не ідентифікується як дійсний медіа-файл"
@@ -1,32 +1,53 @@
1
1
  vi:
2
2
  errors:
3
3
  messages:
4
- content_type_invalid: "tệp không hợp lệ"
5
- spoofed_content_type: "có loại nội dung không phải loại nội dung được khai báo thông qua nội dung, tên tệp và phần mở rộng của nó"
6
- file_size_not_less_than: "kích thước tệp phải nhỏ hơn %{max_size} (kích thước hiện tại là %{file_size})"
7
- file_size_not_less_than_or_equal_to: "kích thước tệp phải nhỏ hơn hoặc bằng %{max_size} (kích thước hiện tại là %{file_size})"
8
- file_size_not_greater_than: "kích thước tệp phải lớn hơn %{min_size} (kích thước hiện tại là %{file_size})"
9
- 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_size} (kích thước hiện tại là %{file_size})"
10
- file_size_not_between: "kích thước tệp phải nằm trong khoảng từ %{min_size} đến %{max_size} (kích thước hiện tại là %{file_size})"
11
- total_file_size_not_less_than: "tổng kích thước tệp phải nhỏ hơn %{max_size} (kích thước hiện tại là %{total_file_size})"
12
- 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_size} (kích thước hiện tại là %{total_file_size})"
13
- total_file_size_not_greater_than: "tổng kích thước tệp phải lớn hơn %{min_size} (kích thước hiện tại là %{total_file_size})"
14
- 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_size} (kích thước hiện tại là %{total_file_size})"
15
- total_file_size_not_between: "tổng kích thước tệp phải nằm trong khoảng từ %{min_size} đến %{max_size} (kích thước hiện tại là %{total_file_size})"
16
- limit_out_of_range: "tổng số tệp vượt giới hạn"
17
- image_metadata_missing: "không phải là ảnh"
18
- dimension_min_inclusion: "phải lớn hơn hoặc bằng %{width} x %{height} pixel"
19
- dimension_max_inclusion: "phải nhỏ hơn hoặc bằng %{width} x %{height} pixel"
20
- dimension_width_inclusion: "chiều rộng không nằm trong %{min} %{max} pixel"
21
- dimension_height_inclusion: "chiều cao không nằm trong %{min} %{max} pixel"
22
- dimension_width_greater_than_or_equal_to: "chiều rộng phải lớn hơn hoặc bằng %{length} pixel"
23
- dimension_height_greater_than_or_equal_to: "chiều cao phải lớn hơn hoặc bằng %{length} pixel"
24
- dimension_width_less_than_or_equal_to: "chiều rộng phải nhỏ hơn hoặc bằng %{length} pixel"
25
- dimension_height_less_than_or_equal_to: "chiều cao phải nhỏ hơn hoặc bằng %{length} pixel"
26
- dimension_width_equal_to: "chiều rộng phải bằng %{length} pixel"
27
- dimension_height_equal_to: "chiều cao phải bằng %{length} pixel"
28
- aspect_ratio_not_square: "phải ảnh hình vuông"
29
- aspect_ratio_not_portrait: "phải là ảnh đứng"
30
- aspect_ratio_not_landscape: "phải ảnh ngang"
31
- aspect_ratio_is_not: "phải có tỉ lệ ảnh %{aspect_ratio}"
32
- image_not_processable: "không phải ảnh"
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 %{autorized_human_content_types})"
6
+ other: " 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: " 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: " 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 %{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 tệp nào được đính kèm (phải giữa các tệp %{min} và %{max})"
27
+ one: "chỉ 1 tệp được đính kèm (phải 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 í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 í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ệ"
@@ -1,32 +1,53 @@
1
1
  zh-CN:
2
2
  errors:
3
3
  messages:
4
- content_type_invalid: "文件类型错误"
5
- spoofed_content_type: "内容类型与通过内容、文件名和扩展名声明的内容类型不同"
6
- file_size_not_less_than: "文件大小必须小于 %{max_size}(当前大小为 %{file_size})"
7
- file_size_not_less_than_or_equal_to: "文件大小必须小于或等于 %{max_size}(当前大小为 %{file_size})"
8
- file_size_not_greater_than: "文件大小必须大于 %{min_size}(当前大小为 %{file_size})"
9
- file_size_not_greater_than_or_equal_to: "文件大小必须大于或等于 %{min_size}(当前大小为 %{file_size})"
10
- file_size_not_between: "文件大小必须介于 %{min_size} %{max_size} 之间(当前大小为 %{file_size})"
11
- total_file_size_not_less_than: "总文件大小必须小于 %{max_size}(当前大小为 %{total_file_size})"
12
- total_file_size_not_less_than_or_equal_to: "文件总大小必须小于或等于 %{max_size}(当前大小为 %{total_file_size})"
13
- total_file_size_not_greater_than: "总文件大小必须大于 %{min_size}(当前大小为 %{total_file_size})"
14
- total_file_size_not_greater_than_or_equal_to: "文件总大小必须大于或等于 %{min_size}(当前大小为 %{total_file_size})"
15
- total_file_size_not_between: "总文件大小必须介于 %{min_size} %{max_size} 之间(当前大小为 %{total_file_size})"
16
- limit_out_of_range: "文件数超出限定范围"
17
- image_metadata_missing: "不是有效的图像"
18
- dimension_min_inclusion: "必须大于或等于 %{width} x %{height} 像素"
19
- dimension_max_inclusion: "必须小于或等于 %{width} x %{height} 像素"
20
- dimension_width_inclusion: "宽度不在 %{min} 和 %{max} 像素之间"
21
- dimension_height_inclusion: "高度不在 %{min} 和 %{max} 像素之间"
22
- dimension_width_greater_than_or_equal_to: "宽度必须大于或等于 %{length} 像素"
23
- dimension_height_greater_than_or_equal_to: "高度必须大于或等于 %{length} 像素"
24
- dimension_width_less_than_or_equal_to: "宽度必须小于或等于 %{length} 像素"
25
- dimension_height_less_than_or_equal_to: "高度必须小于或等于 %{length} 像素"
26
- dimension_width_equal_to: "宽度必须等于 %{length} 像素"
27
- dimension_height_equal_to: "高度必须等于 %{length} 像素"
28
- aspect_ratio_not_square: "必须是方形图片"
29
- aspect_ratio_not_portrait: "必须是竖屏图片"
30
- aspect_ratio_not_landscape: "必须是横屏图片"
31
- aspect_ratio_is_not: "纵横比必须是 %{aspect_ratio}"
32
- image_not_processable: "不是有效的图像"
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,18 +8,11 @@ module ActiveStorageValidations
8
8
 
9
9
  private
10
10
 
11
- def read_image
12
- begin
13
- require "mini_magick" unless defined?(MiniMagick)
14
- rescue LoadError
15
- logger.info "Skipping image analysis because the mini_magick gem isn't installed"
16
- return {}
17
- end
18
-
11
+ def read_media
19
12
  Tempfile.create(binmode: true) do |tempfile|
20
13
  begin
21
- if image(tempfile).valid?
22
- yield image(tempfile)
14
+ if media(tempfile).valid?
15
+ yield media(tempfile)
23
16
  else
24
17
  logger.info "Skipping image analysis because ImageMagick doesn't support the file"
25
18
  {}
@@ -33,7 +26,7 @@ module ActiveStorageValidations
33
26
  {}
34
27
  end
35
28
 
36
- def image_from_path(path)
29
+ def media_from_path(path)
37
30
  instrument("mini_magick") do
38
31
  MiniMagick::Image.new(path)
39
32
  end
@@ -42,5 +35,13 @@ module ActiveStorageValidations
42
35
  def rotated_image?(image)
43
36
  %w[ RightTop LeftBottom TopRight BottomLeft ].include?(image["%[orientation]"])
44
37
  end
38
+
39
+ def supported?
40
+ require "mini_magick"
41
+ true
42
+ rescue LoadError
43
+ logger.info "Skipping image analysis because the mini_magick gem isn't installed"
44
+ false
45
+ end
45
46
  end
46
47
  end
@@ -7,18 +7,11 @@ module ActiveStorageValidations
7
7
 
8
8
  private
9
9
 
10
- def read_image
11
- begin
12
- require "vips" unless defined?(::Vips)
13
- rescue LoadError
14
- logger.info "Skipping image analysis because the ruby-vips gem isn't installed"
15
- return {}
16
- end
17
-
10
+ def read_media
18
11
  Tempfile.create(binmode: true) do |tempfile|
19
12
  begin
20
- if image(tempfile)
21
- yield image(tempfile)
13
+ if media(tempfile)
14
+ yield media(tempfile)
22
15
  else
23
16
  logger.info "Skipping image analysis because Vips doesn't support the file"
24
17
  {}
@@ -32,7 +25,7 @@ module ActiveStorageValidations
32
25
  {}
33
26
  end
34
27
 
35
- def image_from_path(path)
28
+ def media_from_path(path)
36
29
  instrument("vips") do
37
30
  begin
38
31
  ::Vips::Image.new_from_file(path, access: :sequential)
@@ -41,7 +34,6 @@ module ActiveStorageValidations
41
34
  # supported attachable.
42
35
  # We stumbled upon this issue while reading 0 byte size attachable
43
36
  # https://github.com/janko/image_processing/issues/97
44
- logger.info "Skipping image analysis because Vips doesn't support the file"
45
37
  nil
46
38
  end
47
39
  end
@@ -53,5 +45,13 @@ module ActiveStorageValidations
53
45
  rescue ::Vips::Error
54
46
  false
55
47
  end
48
+
49
+ def supported?
50
+ require "vips"
51
+ true
52
+ rescue LoadError
53
+ logger.info "Skipping image analysis because the ruby-vips gem isn't installed"
54
+ false
55
+ end
56
56
  end
57
57
  end