77from keyword import iskeyword , issoftkeyword
88from typing import Annotated , NewType
99
10- from pydantic import BaseModel , ByteSize , PositiveInt , conset , field_validator
10+ from pydantic import BaseModel , ByteSize , PositiveInt , StringConstraints , conset , field_validator
1111from pydantic .fields import Field
1212
1313
@@ -97,7 +97,7 @@ class SourceManifest(BaseModel):
9797 version : Annotated [str , Field (pattern = RE_SEMVER )]
9898 api_version : Annotated [str , Field (pattern = RE_API )]
9999 author : str
100- name : dict [Bcp47LanguageTag , str ] = {}
100+ name : dict [Bcp47LanguageTag , Annotated [ str , StringConstraints ( min_length = 1 )]] = Field ( min_length = 1 )
101101 entrypoint : str | None = None
102102 url : str | None = None
103103 languages : list [Bcp47LanguageTag ] = Field (min_length = 1 )
@@ -119,6 +119,16 @@ class SourceManifest(BaseModel):
119119 def ensure_is_valid_name (cls , value : str ) -> str :
120120 return ensure_is_valid_name (value )
121121
122+ @field_validator ("languages" , "name" )
123+ @classmethod
124+ def ensure_contains_english_translation (
125+ cls , value : list [Bcp47LanguageTag ] | dict [Bcp47LanguageTag , str ]
126+ ) -> list [Bcp47LanguageTag ] | dict [Bcp47LanguageTag , str ]:
127+ if Bcp47LanguageTag ("en" ) not in value :
128+ msg = "must contain an english translation"
129+ raise ValueError (msg )
130+ return value
131+
122132 @property
123133 def identifier (self ) -> str :
124134 return f"@{ self .namespace } /{ self .short_name } "
0 commit comments