diff --git a/src/app/features/project-editor/sections/general-section.component.html b/src/app/features/project-editor/sections/general-section.component.html index c3c26ef..c88c34d 100644 --- a/src/app/features/project-editor/sections/general-section.component.html +++ b/src/app/features/project-editor/sections/general-section.component.html @@ -12,7 +12,7 @@ {{ 'builder.descriptionFieldDesc' | translate }} - + diff --git a/src/app/features/project-editor/sections/general-section.component.ts b/src/app/features/project-editor/sections/general-section.component.ts index c8180a6..c303613 100644 --- a/src/app/features/project-editor/sections/general-section.component.ts +++ b/src/app/features/project-editor/sections/general-section.component.ts @@ -61,12 +61,25 @@ export class ProjectEditorGeneralSectionComponent { })); } + /** + * Routes through facade.addLocale()/removeLocale() (LocaleSyncService) + * instead of overwriting supportedLocales directly - a direct overwrite + * skipped seeding/cleaning up per-locale nav and static-page translation + * entries, leaving them out of sync with what this field claims is + * supported (and Languages' add/remove buttons already do it correctly). + */ updateSupportedLanguages(value: string): void { - const locales = value.split(',').map(item => item.trim()).filter(Boolean); - this.facade.updateBootstrap(current => ({ - ...current, - tenant: { ...current.tenant, supportedLocales: locales }, - localization: { ...current.localization, supportedLocales: locales } - })); + const next = new Set(value.split(',').map(item => item.trim().toLowerCase()).filter(Boolean)); + const current = this.bootstrap()?.localization.supportedLocales ?? []; + for (const locale of current) { + if (!next.has(locale)) { + this.facade.removeLocale(locale); + } + } + for (const locale of next) { + if (!current.includes(locale)) { + this.facade.addLocale(locale); + } + } } } diff --git a/src/app/features/project-editor/services/project-validator.service.ts b/src/app/features/project-editor/services/project-validator.service.ts index 23f290d..da4b69f 100644 --- a/src/app/features/project-editor/services/project-validator.service.ts +++ b/src/app/features/project-editor/services/project-validator.service.ts @@ -70,9 +70,17 @@ export class ProjectValidator { } private languageIssues(bootstrap: BootstrapConfig): ProjectValidationIssue[] { - return bootstrap.localization.supportedLocales.length > 0 - ? [] - : [error('no-languages', 'builder.validationNoLanguages', 'languages', 'localization.supportedLocales')]; + if (bootstrap.localization.supportedLocales.length === 0) { + return [error('no-languages', 'builder.validationNoLanguages', 'languages', 'localization.supportedLocales')]; + } + // General's free-text "Default Language" field (unlike Languages' set-default + // buttons, which only ever target an already-supported locale) can set this + // to any string. A default locale that isn't itself supported breaks every + // `label[defaultLocale]` lookup across nav/static-page content. + if (!bootstrap.localization.supportedLocales.includes(bootstrap.localization.defaultLocale)) { + return [error('default-locale-not-supported', 'builder.validationDefaultLocaleNotSupported', 'general', 'localization.defaultLocale')]; + } + return []; } private urlIssues(bootstrap: BootstrapConfig): ProjectValidationIssue[] { diff --git a/src/app/i18n/en.ts b/src/app/i18n/en.ts index f615664..22e8288 100644 --- a/src/app/i18n/en.ts +++ b/src/app/i18n/en.ts @@ -538,6 +538,7 @@ export const en: Translations = { featureFlags: 'Feature Flags', validationMissingLogo: 'Branding is missing a logo.', validationNoLanguages: 'No languages are configured.', + validationDefaultLocaleNotSupported: 'The default language is not in the supported languages list.', validationInvalidUrl: 'The marketplace URL is invalid.', validationDuplicateSlugs: 'Two or more static pages share the same slug.', validationEmptyHomepage: 'The homepage has no sections.', diff --git a/src/app/i18n/hy.ts b/src/app/i18n/hy.ts index 10af5cd..003379f 100644 --- a/src/app/i18n/hy.ts +++ b/src/app/i18n/hy.ts @@ -538,6 +538,7 @@ export const hy: Translations = { featureFlags: 'Feature flags', validationMissingLogo: 'Բրենդինգում բացակայում է լոգոն։', validationNoLanguages: 'Կարգավորված լեզուներ չկան։', + validationDefaultLocaleNotSupported: 'Կանխադրված լեզուն աջակցվող լեզուների ցանկում չէ։', validationInvalidUrl: 'Մարքեթփլեյսի URL-ը սխալ է։', validationDuplicateSlugs: 'Երկու կամ ավելի ստատիկ էջեր ունեն նույն slug-ը։', validationEmptyHomepage: 'Գլխավոր էջում սեկցիաներ չկան։', diff --git a/src/app/i18n/ru.ts b/src/app/i18n/ru.ts index e57f0a9..bf26a79 100644 --- a/src/app/i18n/ru.ts +++ b/src/app/i18n/ru.ts @@ -538,6 +538,7 @@ export const ru: Translations = { featureFlags: 'Фичи-флаги', validationMissingLogo: 'В брендинге отсутствует логотип.', validationNoLanguages: 'Не настроены языки.', + validationDefaultLocaleNotSupported: 'Язык по умолчанию отсутствует в списке поддерживаемых языков.', validationInvalidUrl: 'Некорректный URL маркетплейса.', validationDuplicateSlugs: 'Две или более статические страницы имеют одинаковый slug.', validationEmptyHomepage: 'На главной странице нет секций.', diff --git a/src/app/i18n/translations.ts b/src/app/i18n/translations.ts index 488dae0..ff4d576 100644 --- a/src/app/i18n/translations.ts +++ b/src/app/i18n/translations.ts @@ -536,6 +536,7 @@ export interface Translations { featureFlags: string; validationMissingLogo: string; validationNoLanguages: string; + validationDefaultLocaleNotSupported: string; validationInvalidUrl: string; validationDuplicateSlugs: string; validationEmptyHomepage: string;