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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +619 -213
  3. data/config/locales/da.yml +50 -30
  4. data/config/locales/de.yml +50 -30
  5. data/config/locales/en.yml +50 -30
  6. data/config/locales/es.yml +50 -30
  7. data/config/locales/fr.yml +50 -30
  8. data/config/locales/it.yml +50 -30
  9. data/config/locales/ja.yml +50 -30
  10. data/config/locales/nl.yml +50 -30
  11. data/config/locales/pl.yml +50 -30
  12. data/config/locales/pt-BR.yml +50 -30
  13. data/config/locales/ru.yml +50 -30
  14. data/config/locales/sv.yml +50 -30
  15. data/config/locales/tr.yml +50 -30
  16. data/config/locales/uk.yml +50 -30
  17. data/config/locales/vi.yml +50 -30
  18. data/config/locales/zh-CN.yml +50 -30
  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 +4 -4
  22. data/lib/active_storage_validations/analyzer/image_analyzer/vips.rb +11 -12
  23. data/lib/active_storage_validations/analyzer/image_analyzer.rb +9 -53
  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 +15 -11
  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 +56 -23
  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 +49 -0
  34. data/lib/active_storage_validations/{marcel_extensor.rb → extensors/asv_marcelable.rb} +3 -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 +5 -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_analyzable.rb +38 -3
  48. data/lib/active_storage_validations/shared/asv_attachable.rb +36 -15
  49. data/lib/active_storage_validations/size_validator.rb +11 -3
  50. data/lib/active_storage_validations/total_size_validator.rb +9 -3
  51. data/lib/active_storage_validations/version.rb +1 -1
  52. data/lib/active_storage_validations.rb +7 -3
  53. metadata +14 -8
  54. data/lib/active_storage_validations/content_type_spoof_detector.rb +0 -96
@@ -1,33 +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"
33
- aspect_ratio_invalid: "geçersiz bir en boy oranına sahip"
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,33 +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: "не є допустимим зображенням"
33
- aspect_ratio_invalid: "має недійсне співвідношення сторін"
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,33 +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"
33
- aspect_ratio_invalid: "có tỷ lệ khung hình không hợp lệ"
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,33 +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: "不是有效的图像"
33
- aspect_ratio_invalid: "宽高比无效"
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 read_image
11
+ def read_media
12
12
  Tempfile.create(binmode: true) do |tempfile|
13
13
  begin
14
- if image(tempfile).valid?
15
- yield image(tempfile)
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 image_from_path(path)
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 read_image
10
+ def read_media
11
11
  Tempfile.create(binmode: true) do |tempfile|
12
12
  begin
13
- if image(tempfile)
14
- yield image(tempfile)
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 image_from_path(path)
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