diff --git a/extensions/package-manager/locale/en.yml b/extensions/package-manager/locale/en.yml index 54d93e731f..2299616681 100755 --- a/extensions/package-manager/locale/en.yml +++ b/extensions/package-manager/locale/en.yml @@ -161,3 +161,23 @@ flarum-extension-manager: why_not_modal: title: Why Won't it Update + + validation: + attributes: + minimum_stability: minimum stability + repositories: repositories + repositories.*: repositories + repositories.*.type: repository type + repositories.*.url: repository URL + extension_id: extension ID + update_mode: update mode + package: package + version: version + github_oauth: GitHub OAuth + github_oauth.*: GitHub OAuth + gitlab_oauth: GitLab OAuth + gitlab_oauth.*: GitLab OAuth + gitlab_token: GitLab Token + gitlab_token.*: GitLab Token + bearer: HTTP Bearer + bearer.*: HTTP Bearer diff --git a/extensions/suspend/locale/en.yml b/extensions/suspend/locale/en.yml index 495c28d5f3..d9c9254a48 100644 --- a/extensions/suspend/locale/en.yml +++ b/extensions/suspend/locale/en.yml @@ -69,3 +69,7 @@ flarum-suspend: You have been unsuspended. You can head back to the forum by clicking on the following link: {forum_url} + + validation: + attributes: + suspendedUntil: suspended until diff --git a/extensions/tags/locale/en.yml b/extensions/tags/locale/en.yml index 3890539d2d..0bca66ead7 100644 --- a/extensions/tags/locale/en.yml +++ b/extensions/tags/locale/en.yml @@ -126,3 +126,13 @@ flarum-tags: choose_tags_placeholder: "{count, plural, one {Choose 1 more tag} other {Choose # more tags}}" name: Name tags: Tags + + validation: + attributes: + name: name + slug: slug + is_hidden: hidden + description: description + color: color + tag_count_primary: => validation.attributes.tag_count_primary + tag_count_secondary: => validation.attributes.tag_count_secondary diff --git a/framework/core/locale/validation.yml b/framework/core/locale/validation.yml index 934d1739d2..b1737c455e 100644 --- a/framework/core/locale/validation.yml +++ b/framework/core/locale/validation.yml @@ -79,6 +79,7 @@ validation: present: "The :attribute field must be present." regex: "The :attribute format is invalid." required: "The :attribute field is required." + required_array_keys: "The :attribute array must contain entries for: :values." required_if: "The :attribute field is required when :other is :value." required_unless: "The :attribute field is required unless :other is in :values." required_with: "The :attribute field is required when :values is present." diff --git a/framework/core/src/Extension/Extension.php b/framework/core/src/Extension/Extension.php index 8cccbd3007..f3cbb51db6 100644 --- a/framework/core/src/Extension/Extension.php +++ b/framework/core/src/Extension/Extension.php @@ -333,6 +333,19 @@ public function getTitle() return $this->composerJsonAttribute('extra.flarum-extension.title'); } + /** + * @return string|null + */ + public function getNamespace(): ?string + { + return Collection::make($this->composerJsonAttribute('autoload.psr-4')) + ->filter(function ($source) { + return $source === 'src/'; + }) + ->keys() + ->first(); + } + /** * @return string */ diff --git a/framework/core/src/Foundation/AbstractValidator.php b/framework/core/src/Foundation/AbstractValidator.php index 5629213aa8..5c0690b8ad 100644 --- a/framework/core/src/Foundation/AbstractValidator.php +++ b/framework/core/src/Foundation/AbstractValidator.php @@ -9,6 +9,7 @@ namespace Flarum\Foundation; +use Illuminate\Contracts\Cache\Store as Cache; use Illuminate\Support\Arr; use Illuminate\Validation\Factory; use Illuminate\Validation\ValidationException; @@ -16,6 +17,13 @@ abstract class AbstractValidator { + use ExtensionIdTrait; + + /** + * @var string + */ + public static $CORE_VALIDATION_CACHE_KEY = 'core.validation.extension_id_class_names'; + /** * @var array */ @@ -81,6 +89,30 @@ protected function getMessages() return []; } + /** + * @return array + */ + protected function getAttributeNames() + { + $cache = resolve(Cache::class); + + if ($cache->get(self::$CORE_VALIDATION_CACHE_KEY) !== null) { + return $cache->get(self::$CORE_VALIDATION_CACHE_KEY); + } + + $extId = $this->getClassExtensionId(); + $attributeNames = []; + + foreach (array_keys($this->rules) as $attribute) { + $key = $extId ? "$extId.validation.attributes.$attribute" : "validation.attributes.$attribute"; + $attributeNames[$attribute] = $this->translator->trans($key); + } + + $cache->forever(self::$CORE_VALIDATION_CACHE_KEY, $attributeNames); + + return $attributeNames; + } + /** * Make a new validator instance for this model. * @@ -92,6 +124,7 @@ protected function makeValidator(array $attributes) $rules = Arr::only($this->getRules(), array_keys($attributes)); $validator = $this->validator->make($attributes, $rules, $this->getMessages()); + $validator->setAttributeNames($this->getAttributeNames()); foreach ($this->configuration as $callable) { $callable($this, $validator); diff --git a/framework/core/src/Foundation/ExtensionIdTrait.php b/framework/core/src/Foundation/ExtensionIdTrait.php new file mode 100644 index 0000000000..7e2bde4e5d --- /dev/null +++ b/framework/core/src/Foundation/ExtensionIdTrait.php @@ -0,0 +1,31 @@ +getExtensions() + ->mapWithKeys(function (Extension $extension) { + return [$extension->getId() => $extension->getNamespace()]; + }) + ->filter(function ($namespace) { + return $namespace && str_starts_with(static::class, $namespace); + }) + ->keys() + ->first(); + } +}