Put locale in compliance portal URLs

Path-segment locales make each language crawlable with self
canonical and hreflang, while identity.locale persists an
explicit choice without client storage or cookie banners.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-07-21 11:02:44 +02:00
parent 2a250ab7d4
commit c223873e96
52 changed files with 1306 additions and 105 deletions

View File

@@ -62,8 +62,18 @@ type (
UpdateIdentityRequest struct {
FullName string `json:"fullName"`
}
UpdateLocaleRequest struct {
Locale string `json:"locale"`
}
)
// Short URL locale tags accepted for Identity.locale (must stay in sync with
// the compliance-portal URL_LOCALES list).
var supportedIdentityLocales = []string{
"en", "fr", "de", "es", "id", "it", "ja", "ko", "pl", "pt", "tr", "uk", "zh",
}
const (
TokenTypeEmailConfirmation = "email_confirmation"
)
@@ -88,6 +98,20 @@ func (req UpdateIdentityRequest) Validate() error {
return v.Error()
}
func (req UpdateLocaleRequest) Validate() error {
v := validator.New()
v.Check(
req.Locale,
"locale",
validator.NotEmpty(),
validator.MaxLen(8),
validator.OneOfSlice(supportedIdentityLocales),
)
return v.Error()
}
func (s AccountService) ChangeEmail(ctx context.Context, identityID gid.GID, req *ChangeEmailRequest) error {
if err := req.Validate(); err != nil {
return fmt.Errorf("invalid request: %w", err)
@@ -402,6 +426,42 @@ func (s AccountService) UpdateIdentity(ctx context.Context, identityID gid.GID,
return identity, nil
}
func (s AccountService) UpdateLocale(ctx context.Context, identityID gid.GID, req *UpdateLocaleRequest) (*coredata.Identity, error) {
if err := req.Validate(); err != nil {
return nil, fmt.Errorf("invalid request: %w", err)
}
identity := &coredata.Identity{}
err := s.pg.WithTx(
ctx,
func(ctx context.Context, tx pg.Tx) error {
err := identity.LoadByID(ctx, tx, identityID)
if err != nil {
if err == coredata.ErrResourceNotFound {
return NewIdentityNotFoundError(identityID)
}
return fmt.Errorf("cannot load identity: %w", err)
}
identity.Locale = &req.Locale
identity.UpdatedAt = time.Now()
if err := identity.Update(ctx, tx); err != nil {
return fmt.Errorf("cannot update identity locale: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return identity, nil
}
func (s AccountService) ListPersonalAPIKeys(
ctx context.Context,
identityID gid.GID,