fix
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Admin orgs UI client — users + companies directory, staff roles, plan assign,
|
||||
* clone-catalog, and Fix A1 (`POST …/fix-catalog`).
|
||||
* Flash Fix A1: result.prompts / hashes / categories → flash.admin.fixA1Success.
|
||||
* clone-catalog, and Sync A1 (`POST …/sync-a1`; fix-catalog is a compat alias).
|
||||
* Flash Sync A1: result.prompts / hashes / categories / dump_* → flash.admin.syncA1Success.
|
||||
* Contract: docs/admin-roles-support/04-contract.md · Docs: 10-admin-orgs-ui.md
|
||||
*/
|
||||
import { api, ApiError } from "$lib/api";
|
||||
@@ -22,6 +22,8 @@ export const ADMIN_CLONE_CATALOG_PATH = (companyId: string) =>
|
||||
`${ADMIN_COMPANIES_PATH}/${encodeURIComponent(companyId)}/clone-catalog`;
|
||||
export const ADMIN_FIX_CATALOG_PATH = (companyId: string) =>
|
||||
`${ADMIN_COMPANIES_PATH}/${encodeURIComponent(companyId)}/fix-catalog`;
|
||||
export const ADMIN_SYNC_A1_PATH = (companyId: string) =>
|
||||
`${ADMIN_COMPANIES_PATH}/${encodeURIComponent(companyId)}/sync-a1`;
|
||||
export const ADMIN_STAFF_ROLE_PATH = (userId: string) =>
|
||||
`/api/admin/users/${encodeURIComponent(userId)}/staff-role`;
|
||||
|
||||
@@ -230,13 +232,13 @@ export async function cloneAdminCompanyCatalog(
|
||||
});
|
||||
}
|
||||
|
||||
export type FixCatalogResult = {
|
||||
export type SyncA1Result = {
|
||||
company_id: string;
|
||||
company_name: string;
|
||||
a1_cohort?: boolean;
|
||||
category_attribute_orphans_removed?: number;
|
||||
category_attribute_links?: number;
|
||||
/** Alias of category_prompts_updated for flash.admin.fixA1Success {prompts}. */
|
||||
/** Alias of category_prompts_updated for flash.admin.syncA1Success {prompts}. */
|
||||
prompts?: number;
|
||||
category_prompts_updated?: number;
|
||||
product_enhance_languages?: number;
|
||||
@@ -258,23 +260,36 @@ export type FixCatalogResult = {
|
||||
products_scanned?: number;
|
||||
reprocess_needed_count?: number;
|
||||
reprocess_sample_raw_product_ids?: string[];
|
||||
dump_found?: boolean;
|
||||
dump_path?: string;
|
||||
dump_skipped_reason?: string;
|
||||
dump_pairs?: number;
|
||||
dump_mapped_updated?: number;
|
||||
dump_processed_updated?: number;
|
||||
dump_status?: string;
|
||||
};
|
||||
|
||||
export type FixCatalogResponse = {
|
||||
export type SyncA1Response = {
|
||||
status: string;
|
||||
result: FixCatalogResult;
|
||||
result: SyncA1Result;
|
||||
note?: string;
|
||||
};
|
||||
|
||||
/** In-place Fix A1 / catalog hygiene. Never clears catalog; no mass reprocess. */
|
||||
export async function fixAdminCompanyCatalog(
|
||||
/** @deprecated Use SyncA1Result — kept for type aliases during UI rename. */
|
||||
export type FixCatalogResult = SyncA1Result;
|
||||
/** @deprecated Use SyncA1Response */
|
||||
export type FixCatalogResponse = SyncA1Response;
|
||||
|
||||
/** Sync A1: dump category backfill (when dump on API host) + Fix hygiene. No mass reprocess. */
|
||||
export async function syncAdminCompanyA1(
|
||||
companyId: string,
|
||||
opts?: { backfillCategories?: boolean; reprocessSampleLimit?: number }
|
||||
): Promise<FixCatalogResponse> {
|
||||
opts?: { backfillCategories?: boolean; reprocessSampleLimit?: number; skipDumpBackfill?: boolean }
|
||||
): Promise<SyncA1Response> {
|
||||
const body: {
|
||||
confirm: true;
|
||||
backfill_categories?: boolean;
|
||||
reprocess_sample_limit?: number;
|
||||
skip_dump_backfill?: boolean;
|
||||
} = { confirm: true };
|
||||
if (opts?.backfillCategories === false) {
|
||||
body.backfill_categories = false;
|
||||
@@ -282,12 +297,23 @@ export async function fixAdminCompanyCatalog(
|
||||
if (typeof opts?.reprocessSampleLimit === "number") {
|
||||
body.reprocess_sample_limit = opts.reprocessSampleLimit;
|
||||
}
|
||||
return api<FixCatalogResponse>(ADMIN_FIX_CATALOG_PATH(companyId), {
|
||||
if (opts?.skipDumpBackfill) {
|
||||
body.skip_dump_backfill = true;
|
||||
}
|
||||
return api<SyncA1Response>(ADMIN_SYNC_A1_PATH(companyId), {
|
||||
method: "POST",
|
||||
body
|
||||
});
|
||||
}
|
||||
|
||||
/** Compat alias — same as syncAdminCompanyA1 (fix-catalog route). */
|
||||
export async function fixAdminCompanyCatalog(
|
||||
companyId: string,
|
||||
opts?: { backfillCategories?: boolean; reprocessSampleLimit?: number }
|
||||
): Promise<SyncA1Response> {
|
||||
return syncAdminCompanyA1(companyId, opts);
|
||||
}
|
||||
|
||||
export function isStaffRoleApiUnavailable(err: unknown): boolean {
|
||||
return err instanceof ApiError && (err.status === 404 || err.status === 501);
|
||||
}
|
||||
|
||||
@@ -812,14 +812,14 @@ export const de: MessageDict = {
|
||||
"admin.users.cloneCatalogCancel": "Abbrechen",
|
||||
"admin.users.cloneCatalogConfirm": "Katalog kopieren",
|
||||
"admin.users.cloneDestFallback": "Ihr Sandbox-Unternehmen",
|
||||
"admin.users.fixA1": "A1-Katalog reparieren",
|
||||
"admin.users.fixA1Aria": "KI-Prompts, Kategorien und Enhance-Hashes für {name} reparieren",
|
||||
"admin.users.fixA1Title": "Unternehmenskatalog reparieren",
|
||||
"admin.users.fixA1Desc": "Wendet korrigierte KI-Prompts erneut an, löst schwache Enhance-Hashes und füllt Kategorien aus mapped_data nach.",
|
||||
"admin.users.fixA1Company": "Unternehmen: {name}",
|
||||
"admin.users.fixA1Warning": "Bevorzugen Sie Platform Demo oder ein explizites Unternehmen. Löscht keine Feeds, Mappings oder Rohprodukte. Schützt A1-Kohorten-Überschreibregeln.",
|
||||
"admin.users.fixA1Cancel": "Abbrechen",
|
||||
"admin.users.fixA1Confirm": "Katalog reparieren",
|
||||
"admin.users.syncA1": "A1 synchronisieren",
|
||||
"admin.users.syncA1Aria": "Sync A1 categories from dump and repair catalog hygiene for {name}",
|
||||
"admin.users.syncA1Title": "A1-Katalog synchronisieren",
|
||||
"admin.users.syncA1Desc": "Backfills mapped categories from the MySQL dump when present on the API host, then runs catalog hygiene (prompts, weak hashes, bidirectional category backfill, attribute sanitize). Does not wipe or reimport the full catalog.",
|
||||
"admin.users.syncA1Company": "Company: {name}",
|
||||
"admin.users.syncA1Warning": "Requires descrybe_new.sql on the API server (scripts/seed/ or SEED_A1_MYSQL_DUMP) for dump category coverage. Without a dump, only DB hygiene runs. No mass reprocess.",
|
||||
"admin.users.syncA1Cancel": "Abbrechen",
|
||||
"admin.users.syncA1Confirm": "A1 synchronisieren",
|
||||
"admin.users.noUsers": "Keine Benutzer entsprechen diesem Filter.",
|
||||
"admin.users.noCompanies": "Keine Unternehmen entsprechen diesem Filter.",
|
||||
"admin.users.assignRoleTitle": "Mitarbeiterrolle zuweisen",
|
||||
@@ -2305,8 +2305,8 @@ export const de: MessageDict = {
|
||||
"flash.admin.staffRoleUnavailable": "Mitarbeiterrollen-Updates sind auf diesem Server noch nicht verfügbar.",
|
||||
"flash.admin.planAssigned": "Plan {name} zugewiesen.",
|
||||
"flash.admin.catalogCloned": "Copied {source} into {dest}: {products} products, {categories} taxonomy categories, {mapped_with} with mapped category.",
|
||||
"flash.admin.fixA1Success": "Catalog repair finished for {name}: {prompts} prompts, {hashes} hashes, {categories} processed←mapped, {mapped_backfilled} mapped←processed. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.fixA1Error": "Katalogreparatur für {name} fehlgeschlagen.",
|
||||
"flash.admin.syncA1Success": "Synced A1 for {name}: dump_mapped {dump_mapped} ({dump_status}), prompts {prompts}, hashes {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.syncA1Error": "A1-Sync für {name} fehlgeschlagen.",
|
||||
"flash.admin.cloneDestMissing": "No sandbox destination. Switch to Platform Demo (staff home), then clone again.",
|
||||
"flash.admin.planAssignedShort": "Plan zugewiesen.",
|
||||
"flash.admin.creditsUpdated": "Credits aktualisiert.",
|
||||
|
||||
@@ -839,14 +839,14 @@ export const en: MessageDict = {
|
||||
"admin.users.cloneCatalogCancel": "Cancel",
|
||||
"admin.users.cloneCatalogConfirm": "Copy catalog",
|
||||
"admin.users.cloneDestFallback": "your sandbox company",
|
||||
"admin.users.fixA1": "Fix A1 catalog",
|
||||
"admin.users.fixA1Aria": "Repair AI prompts, categories, and enhance hashes for {name}",
|
||||
"admin.users.fixA1Title": "Fix company catalog",
|
||||
"admin.users.fixA1Desc": "In-place repair: category attribute links, category enhance prompts, weak enhance hashes, bidirectional category backfill (mapped↔processed when data exists), attribute sanitize. No mass reprocess. Does not invent categories for unmapped SKUs.",
|
||||
"admin.users.fixA1Company": "Company: {name}",
|
||||
"admin.users.fixA1Warning": "Repairs existing category data only. Products UI uses mapped_data.category — Fix cannot invent missing feed categories. For full A1 coverage run seed-a1 -mode backfill-categories with the MySQL dump, then clone A1 → sandbox.",
|
||||
"admin.users.fixA1Cancel": "Cancel",
|
||||
"admin.users.fixA1Confirm": "Fix catalog",
|
||||
"admin.users.syncA1": "Sync A1",
|
||||
"admin.users.syncA1Aria": "Sync A1 categories from dump and repair catalog hygiene for {name}",
|
||||
"admin.users.syncA1Title": "Sync A1 catalog",
|
||||
"admin.users.syncA1Desc": "Backfills mapped categories from the MySQL dump when present on the API host, then runs catalog hygiene (prompts, weak hashes, bidirectional category backfill, attribute sanitize). Does not wipe or reimport the full catalog.",
|
||||
"admin.users.syncA1Company": "Company: {name}",
|
||||
"admin.users.syncA1Warning": "Requires descrybe_new.sql on the API server (scripts/seed/ or SEED_A1_MYSQL_DUMP) for dump category coverage. Without a dump, only DB hygiene runs. No mass reprocess.",
|
||||
"admin.users.syncA1Cancel": "Cancel",
|
||||
"admin.users.syncA1Confirm": "Sync A1",
|
||||
"admin.users.noUsers": "No users match this filter.",
|
||||
"admin.users.noCompanies": "No companies match this filter.",
|
||||
"admin.users.assignRoleTitle": "Assign staff role",
|
||||
@@ -2334,8 +2334,8 @@ export const en: MessageDict = {
|
||||
"flash.admin.staffRoleUnavailable": "Staff role updates are not available on this server yet.",
|
||||
"flash.admin.planAssigned": "Plan assigned to {name}.",
|
||||
"flash.admin.catalogCloned": "Copied {source} into {dest}: {products} products, {categories} taxonomy categories, {mapped_with} products with mapped category. Open Products — uncategorized SKUs need dump backfill or categorize, not another Fix.",
|
||||
"flash.admin.fixA1Success": "Catalog repair finished for {name}: {prompts} prompts, {hashes} hashes, {categories} processed←mapped, {mapped_backfilled} mapped←processed. Coverage: {mapped_with}/{mapped_total} raw products have mapped categories ({taxonomy} taxonomy rows).",
|
||||
"flash.admin.fixA1Error": "Catalog repair failed for {name}.",
|
||||
"flash.admin.syncA1Success": "Synced A1 for {name}: dump_mapped {dump_mapped} ({dump_status}), prompts {prompts}, hashes {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.syncA1Error": "Sync A1 failed for {name}.",
|
||||
"flash.admin.cloneDestMissing": "No sandbox destination. Switch active company to Platform Demo (or your staff home), then clone again. Clone refuses to overwrite A1.",
|
||||
"flash.admin.planAssignedShort": "Plan assigned.",
|
||||
"flash.admin.creditsUpdated": "Credits updated.",
|
||||
|
||||
@@ -812,14 +812,14 @@ export const es: MessageDict = {
|
||||
"admin.users.cloneCatalogCancel": "Cancelar",
|
||||
"admin.users.cloneCatalogConfirm": "Copiar catálogo",
|
||||
"admin.users.cloneDestFallback": "tu empresa sandbox",
|
||||
"admin.users.fixA1": "Reparar catálogo A1",
|
||||
"admin.users.fixA1Aria": "Reparar prompts de IA, categorÃas y hashes de enhance para {name}",
|
||||
"admin.users.fixA1Title": "Reparar catálogo de la empresa",
|
||||
"admin.users.fixA1Desc": "Vuelve a aplicar prompts de IA corregidos, limpia hashes de enhance débiles y completa categorÃas desde mapped_data.",
|
||||
"admin.users.fixA1Company": "Empresa: {name}",
|
||||
"admin.users.fixA1Warning": "Prefiera Platform Demo o una empresa explÃcita. No elimina feeds, mapeos ni productos en bruto. Protege las reglas de sobrescritura de la cohorte A1.",
|
||||
"admin.users.fixA1Cancel": "Cancelar",
|
||||
"admin.users.fixA1Confirm": "Reparar catálogo",
|
||||
"admin.users.syncA1": "Sincronizar A1",
|
||||
"admin.users.syncA1Aria": "Sync A1 categories from dump and repair catalog hygiene for {name}",
|
||||
"admin.users.syncA1Title": "Sincronizar catálogo A1",
|
||||
"admin.users.syncA1Desc": "Backfills mapped categories from the MySQL dump when present on the API host, then runs catalog hygiene (prompts, weak hashes, bidirectional category backfill, attribute sanitize). Does not wipe or reimport the full catalog.",
|
||||
"admin.users.syncA1Company": "Company: {name}",
|
||||
"admin.users.syncA1Warning": "Requires descrybe_new.sql on the API server (scripts/seed/ or SEED_A1_MYSQL_DUMP) for dump category coverage. Without a dump, only DB hygiene runs. No mass reprocess.",
|
||||
"admin.users.syncA1Cancel": "Cancelar",
|
||||
"admin.users.syncA1Confirm": "Sincronizar A1",
|
||||
"admin.users.noUsers": "Ningún usuario coincide con este filtro.",
|
||||
"admin.users.noCompanies": "Ninguna empresa coincide con este filtro.",
|
||||
"admin.users.assignRoleTitle": "Asignar rol de personal",
|
||||
@@ -2304,8 +2304,8 @@ export const es: MessageDict = {
|
||||
"flash.admin.staffRoleUpdated": "Rol de personal actualizado para {email}.",
|
||||
"flash.admin.staffRoleUnavailable": "Las actualizaciones de rol de personal aún no están disponibles en este servidor.",
|
||||
"flash.admin.catalogCloned": "Copied {source} into {dest}: {products} products, {categories} taxonomy categories, {mapped_with} with mapped category.",
|
||||
"flash.admin.fixA1Success": "Catalog repair finished for {name}: {prompts} prompts, {hashes} hashes, {categories} processed←mapped, {mapped_backfilled} mapped←processed. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.fixA1Error": "Falló la reparación del catálogo de {name}.",
|
||||
"flash.admin.syncA1Success": "Synced A1 for {name}: dump_mapped {dump_mapped} ({dump_status}), prompts {prompts}, hashes {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.syncA1Error": "Falló la sincronización A1 de {name}.",
|
||||
"flash.admin.cloneDestMissing": "No sandbox destination. Switch to Platform Demo (staff home), then clone again.",
|
||||
"flash.admin.planAssigned": "Plan asignado a {name}.",
|
||||
"flash.admin.planAssignedShort": "Plan asignado.",
|
||||
|
||||
@@ -812,14 +812,14 @@ export const fr: MessageDict = {
|
||||
"admin.users.cloneCatalogCancel": "Annuler",
|
||||
"admin.users.cloneCatalogConfirm": "Copier le catalogue",
|
||||
"admin.users.cloneDestFallback": "votre entreprise sandbox",
|
||||
"admin.users.fixA1": "Réparer le catalogue A1",
|
||||
"admin.users.fixA1Aria": "Réparer les prompts IA, catégories et hashes enhance pour {name}",
|
||||
"admin.users.fixA1Title": "Réparer le catalogue entreprise",
|
||||
"admin.users.fixA1Desc": "Réapplique les prompts IA corrigés, efface les hashes enhance faibles et complète les catégories depuis mapped_data.",
|
||||
"admin.users.fixA1Company": "Entreprise : {name}",
|
||||
"admin.users.fixA1Warning": "Préférer Platform Demo ou une entreprise explicite. Ne supprime ni feeds, ni mappings, ni produits bruts. Protège les règles d'écrasement de la cohorte A1.",
|
||||
"admin.users.fixA1Cancel": "Annuler",
|
||||
"admin.users.fixA1Confirm": "Réparer le catalogue",
|
||||
"admin.users.syncA1": "Synchroniser A1",
|
||||
"admin.users.syncA1Aria": "Sync A1 categories from dump and repair catalog hygiene for {name}",
|
||||
"admin.users.syncA1Title": "Synchroniser le catalogue A1",
|
||||
"admin.users.syncA1Desc": "Backfills mapped categories from the MySQL dump when present on the API host, then runs catalog hygiene (prompts, weak hashes, bidirectional category backfill, attribute sanitize). Does not wipe or reimport the full catalog.",
|
||||
"admin.users.syncA1Company": "Company: {name}",
|
||||
"admin.users.syncA1Warning": "Requires descrybe_new.sql on the API server (scripts/seed/ or SEED_A1_MYSQL_DUMP) for dump category coverage. Without a dump, only DB hygiene runs. No mass reprocess.",
|
||||
"admin.users.syncA1Cancel": "Annuler",
|
||||
"admin.users.syncA1Confirm": "Synchroniser A1",
|
||||
"admin.users.noUsers": "Aucun utilisateur ne correspond à ce filtre.",
|
||||
"admin.users.noCompanies": "Aucune entreprise ne correspond à ce filtre.",
|
||||
"admin.users.assignRoleTitle": "Assigner un rôle du personnel",
|
||||
@@ -2304,8 +2304,8 @@ export const fr: MessageDict = {
|
||||
"flash.admin.staffRoleUpdated": "Rôle du personnel mis à jour pour {email}.",
|
||||
"flash.admin.staffRoleUnavailable": "Les mises à jour de rôle personnel ne sont pas encore disponibles sur ce serveur.",
|
||||
"flash.admin.catalogCloned": "Copied {source} into {dest}: {products} products, {categories} taxonomy categories, {mapped_with} with mapped category.",
|
||||
"flash.admin.fixA1Success": "Catalog repair finished for {name}: {prompts} prompts, {hashes} hashes, {categories} processed←mapped, {mapped_backfilled} mapped←processed. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.fixA1Error": "Échec de la réparation du catalogue pour {name}.",
|
||||
"flash.admin.syncA1Success": "Synced A1 for {name}: dump_mapped {dump_mapped} ({dump_status}), prompts {prompts}, hashes {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.syncA1Error": "Échec de la synchronisation A1 pour {name}.",
|
||||
"flash.admin.cloneDestMissing": "No sandbox destination. Switch to Platform Demo (staff home), then clone again.",
|
||||
"flash.admin.planAssigned": "Offre assignée à {name}.",
|
||||
"flash.admin.planAssignedShort": "Offre assignée.",
|
||||
|
||||
@@ -812,14 +812,14 @@ export const it: MessageDict = {
|
||||
"admin.users.cloneCatalogCancel": "Annulla",
|
||||
"admin.users.cloneCatalogConfirm": "Copia catalogo",
|
||||
"admin.users.cloneDestFallback": "la tua azienda sandbox",
|
||||
"admin.users.fixA1": "Ripara catalogo A1",
|
||||
"admin.users.fixA1Aria": "Ripara prompt IA, categorie e hash enhance per {name}",
|
||||
"admin.users.fixA1Title": "Ripara catalogo azienda",
|
||||
"admin.users.fixA1Desc": "Riapplica i prompt IA corretti, cancella hash enhance deboli e completa le categorie da mapped_data.",
|
||||
"admin.users.fixA1Company": "Azienda: {name}",
|
||||
"admin.users.fixA1Warning": "Preferisci Platform Demo o un'azienda esplicita. Non elimina feed, mapping o prodotti grezzi. Protegge le regole di sovrascrittura della coorte A1.",
|
||||
"admin.users.fixA1Cancel": "Annulla",
|
||||
"admin.users.fixA1Confirm": "Ripara catalogo",
|
||||
"admin.users.syncA1": "Sincronizza A1",
|
||||
"admin.users.syncA1Aria": "Sync A1 categories from dump and repair catalog hygiene for {name}",
|
||||
"admin.users.syncA1Title": "Sincronizza catalogo A1",
|
||||
"admin.users.syncA1Desc": "Backfills mapped categories from the MySQL dump when present on the API host, then runs catalog hygiene (prompts, weak hashes, bidirectional category backfill, attribute sanitize). Does not wipe or reimport the full catalog.",
|
||||
"admin.users.syncA1Company": "Company: {name}",
|
||||
"admin.users.syncA1Warning": "Requires descrybe_new.sql on the API server (scripts/seed/ or SEED_A1_MYSQL_DUMP) for dump category coverage. Without a dump, only DB hygiene runs. No mass reprocess.",
|
||||
"admin.users.syncA1Cancel": "Annulla",
|
||||
"admin.users.syncA1Confirm": "Sincronizza A1",
|
||||
"admin.users.noUsers": "Nessun utente corrisponde a questo filtro.",
|
||||
"admin.users.noCompanies": "Nessuna azienda corrisponde a questo filtro.",
|
||||
"admin.users.assignRoleTitle": "Assegna ruolo staff",
|
||||
@@ -2304,8 +2304,8 @@ export const it: MessageDict = {
|
||||
"flash.admin.staffRoleUpdated": "Ruolo staff aggiornato per {email}.",
|
||||
"flash.admin.staffRoleUnavailable": "Gli aggiornamenti del ruolo staff non sono ancora disponibili su questo server.",
|
||||
"flash.admin.catalogCloned": "Copied {source} into {dest}: {products} products, {categories} taxonomy categories, {mapped_with} with mapped category.",
|
||||
"flash.admin.fixA1Success": "Catalog repair finished for {name}: {prompts} prompts, {hashes} hashes, {categories} processed←mapped, {mapped_backfilled} mapped←processed. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.fixA1Error": "Riparazione catalogo per {name} non riuscita.",
|
||||
"flash.admin.syncA1Success": "Synced A1 for {name}: dump_mapped {dump_mapped} ({dump_status}), prompts {prompts}, hashes {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.syncA1Error": "Sincronizzazione A1 per {name} non riuscita.",
|
||||
"flash.admin.cloneDestMissing": "No sandbox destination. Switch to Platform Demo (staff home), then clone again.",
|
||||
"flash.admin.planAssigned": "Piano assegnato a {name}.",
|
||||
"flash.admin.planAssignedShort": "Piano assegnato.",
|
||||
|
||||
@@ -812,14 +812,14 @@ export const ja: MessageDict = {
|
||||
"admin.users.cloneCatalogCancel": "ã‚ャンセル",
|
||||
"admin.users.cloneCatalogConfirm": "ã‚«ã‚¿ãƒã‚°ã‚’コピー",
|
||||
"admin.users.cloneDestFallback": "サンドボックス会社",
|
||||
"admin.users.fixA1": "A1ã‚«ã‚¿ãƒã‚°ã‚’修復",
|
||||
"admin.users.fixA1Aria": "{name} ã®AIプãƒãƒ³ãƒ—トã€ã‚«ãƒ†ã‚´ãƒªã€enhanceãƒãƒƒã‚·ãƒ¥ã‚’修復",
|
||||
"admin.users.fixA1Title": "会社カタãƒã‚°ã‚’修復",
|
||||
"admin.users.fixA1Desc": "ä¿®æ£æ¸ˆã¿AIプãƒãƒ³ãƒ—トをå†é©ç”¨ã—ã€å¼±ã„enhanceãƒãƒƒã‚·ãƒ¥ã‚’消去ã—ã€mapped_dataã‹ã‚‰ã‚«ãƒ†ã‚´ãƒªã‚’補完ã—ã¾ã™ã€‚",
|
||||
"admin.users.fixA1Company": "会社: {name}",
|
||||
"admin.users.fixA1Warning": "Platform Demoã¾ãŸã¯æ˜Žç¤ºçš„ãªä¼šç¤¾ã‚’優先ã—ã¦ãã ã•ã„。フィードã€ãƒžãƒƒãƒ”ングã€ç”Ÿè£½å“ã¯å‰Šé™¤ã—ã¾ã›ã‚“。A1コホートã®ä¸Šæ›¸ãルールをä¿è·ã—ã¾ã™ã€‚",
|
||||
"admin.users.fixA1Cancel": "ã‚ャンセル",
|
||||
"admin.users.fixA1Confirm": "ã‚«ã‚¿ãƒã‚°ã‚’修復",
|
||||
"admin.users.syncA1": "A1を同期",
|
||||
"admin.users.syncA1Aria": "Sync A1 categories from dump and repair catalog hygiene for {name}",
|
||||
"admin.users.syncA1Title": "A1カタログを同期",
|
||||
"admin.users.syncA1Desc": "Backfills mapped categories from the MySQL dump when present on the API host, then runs catalog hygiene (prompts, weak hashes, bidirectional category backfill, attribute sanitize). Does not wipe or reimport the full catalog.",
|
||||
"admin.users.syncA1Company": "Company: {name}",
|
||||
"admin.users.syncA1Warning": "Requires descrybe_new.sql on the API server (scripts/seed/ or SEED_A1_MYSQL_DUMP) for dump category coverage. Without a dump, only DB hygiene runs. No mass reprocess.",
|
||||
"admin.users.syncA1Cancel": "キャンセル",
|
||||
"admin.users.syncA1Confirm": "A1を同期",
|
||||
"admin.users.noUsers": "ã“ã®ãƒ•ィルタã«ä¸€è‡´ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã„ã¾ã›ã‚“。",
|
||||
"admin.users.noCompanies": "ã“ã®ãƒ•ィルタã«ä¸€è‡´ã™ã‚‹ä¼šç¤¾ã¯ã‚りã¾ã›ã‚“。",
|
||||
"admin.users.assignRoleTitle": "スタッフãƒãƒ¼ãƒ«ã‚’割り当ã¦",
|
||||
@@ -2304,8 +2304,8 @@ export const ja: MessageDict = {
|
||||
"flash.admin.staffRoleUpdated": "{email} ã®ã‚¹ã‚¿ãƒƒãƒ•ãƒãƒ¼ãƒ«ã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚",
|
||||
"flash.admin.staffRoleUnavailable": "ã“ã®ã‚µãƒ¼ãƒãƒ¼ã§ã¯ã‚¹ã‚¿ãƒƒãƒ•ãƒãƒ¼ãƒ«ã®æ›´æ–°ã¯ã¾ã 利用ã§ãã¾ã›ã‚“。",
|
||||
"flash.admin.catalogCloned": "Copied {source} into {dest}: {products} products, {categories} taxonomy categories, {mapped_with} with mapped category.",
|
||||
"flash.admin.fixA1Success": "Catalog repair finished for {name}: {prompts} prompts, {hashes} hashes, {categories} processed←mapped, {mapped_backfilled} mapped←processed. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.fixA1Error": "{name} ã®ã‚«ã‚¿ãƒã‚°ä¿®å¾©ã«å¤±æ•—ã—ã¾ã—ãŸã€‚",
|
||||
"flash.admin.syncA1Success": "Synced A1 for {name}: dump_mapped {dump_mapped} ({dump_status}), prompts {prompts}, hashes {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.syncA1Error": "{name} のA1同期に失敗しました。",
|
||||
"flash.admin.cloneDestMissing": "No sandbox destination. Switch to Platform Demo (staff home), then clone again.",
|
||||
"flash.admin.planAssigned": "{name} ã«ãƒ—ランを割り当ã¦ã¾ã—ãŸã€‚",
|
||||
"flash.admin.planAssignedShort": "プランを割り当ã¦ã¾ã—ãŸã€‚",
|
||||
|
||||
@@ -812,14 +812,14 @@ export const nl: MessageDict = {
|
||||
"admin.users.cloneCatalogCancel": "Annuleren",
|
||||
"admin.users.cloneCatalogConfirm": "Catalogus kopiëren",
|
||||
"admin.users.cloneDestFallback": "je sandboxbedrijf",
|
||||
"admin.users.fixA1": "A1-catalogus repareren",
|
||||
"admin.users.fixA1Aria": "AI-prompts, categorieën en enhance-hashes voor {name} repareren",
|
||||
"admin.users.fixA1Title": "Bedrijfscatalogus repareren",
|
||||
"admin.users.fixA1Desc": "Past gecorrigeerde AI-prompts opnieuw toe, wist zwakke enhance-hashes en vult categorieën bij vanuit mapped_data.",
|
||||
"admin.users.fixA1Company": "Bedrijf: {name}",
|
||||
"admin.users.fixA1Warning": "Geef voorkeur aan Platform Demo of een expliciet bedrijf. Verwijdert geen feeds, mappings of ruwe producten. Beschermt A1-cohort-overschrijfregels.",
|
||||
"admin.users.fixA1Cancel": "Annuleren",
|
||||
"admin.users.fixA1Confirm": "Catalogus repareren",
|
||||
"admin.users.syncA1": "A1 synchroniseren",
|
||||
"admin.users.syncA1Aria": "Sync A1 categories from dump and repair catalog hygiene for {name}",
|
||||
"admin.users.syncA1Title": "A1-catalogus synchroniseren",
|
||||
"admin.users.syncA1Desc": "Backfills mapped categories from the MySQL dump when present on the API host, then runs catalog hygiene (prompts, weak hashes, bidirectional category backfill, attribute sanitize). Does not wipe or reimport the full catalog.",
|
||||
"admin.users.syncA1Company": "Company: {name}",
|
||||
"admin.users.syncA1Warning": "Requires descrybe_new.sql on the API server (scripts/seed/ or SEED_A1_MYSQL_DUMP) for dump category coverage. Without a dump, only DB hygiene runs. No mass reprocess.",
|
||||
"admin.users.syncA1Cancel": "Annuleren",
|
||||
"admin.users.syncA1Confirm": "A1 synchroniseren",
|
||||
"admin.users.noUsers": "Geen gebruikers komen overeen met dit filter.",
|
||||
"admin.users.noCompanies": "Geen bedrijven komen overeen met dit filter.",
|
||||
"admin.users.assignRoleTitle": "Medewerkerrol toewijzen",
|
||||
@@ -2304,8 +2304,8 @@ export const nl: MessageDict = {
|
||||
"flash.admin.staffRoleUpdated": "Personeelsrol bijgewerkt voor {email}.",
|
||||
"flash.admin.staffRoleUnavailable": "Personeelsrolupdates zijn op deze server nog niet beschikbaar.",
|
||||
"flash.admin.catalogCloned": "Copied {source} into {dest}: {products} products, {categories} taxonomy categories, {mapped_with} with mapped category.",
|
||||
"flash.admin.fixA1Success": "Catalog repair finished for {name}: {prompts} prompts, {hashes} hashes, {categories} processed←mapped, {mapped_backfilled} mapped←processed. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.fixA1Error": "Catalogusreparatie voor {name} mislukt.",
|
||||
"flash.admin.syncA1Success": "Synced A1 for {name}: dump_mapped {dump_mapped} ({dump_status}), prompts {prompts}, hashes {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.syncA1Error": "A1-synchronisatie voor {name} mislukt.",
|
||||
"flash.admin.cloneDestMissing": "No sandbox destination. Switch to Platform Demo (staff home), then clone again.",
|
||||
"flash.admin.planAssigned": "Plan toegewezen aan {name}.",
|
||||
"flash.admin.planAssignedShort": "Plan toegewezen.",
|
||||
|
||||
@@ -812,14 +812,14 @@ export const pl: MessageDict = {
|
||||
"admin.users.cloneCatalogCancel": "Anuluj",
|
||||
"admin.users.cloneCatalogConfirm": "Kopiuj katalog",
|
||||
"admin.users.cloneDestFallback": "twoja firma sandbox",
|
||||
"admin.users.fixA1": "Napraw katalog A1",
|
||||
"admin.users.fixA1Aria": "Napraw prompty AI, kategorie i hashe enhance dla {name}",
|
||||
"admin.users.fixA1Title": "Napraw katalog firmy",
|
||||
"admin.users.fixA1Desc": "Ponownie stosuje poprawione prompty AI, czyści słabe hashe enhance i uzupełnia kategorie z mapped_data.",
|
||||
"admin.users.fixA1Company": "Firma: {name}",
|
||||
"admin.users.fixA1Warning": "Preferuj Platform Demo lub wskazaną firmę. Nie usuwa feedów, mapowań ani surowych produktów. Chroni reguły nadpisywania kohorty A1.",
|
||||
"admin.users.fixA1Cancel": "Anuluj",
|
||||
"admin.users.fixA1Confirm": "Napraw katalog",
|
||||
"admin.users.syncA1": "Synchronizuj A1",
|
||||
"admin.users.syncA1Aria": "Sync A1 categories from dump and repair catalog hygiene for {name}",
|
||||
"admin.users.syncA1Title": "Synchronizuj katalog A1",
|
||||
"admin.users.syncA1Desc": "Backfills mapped categories from the MySQL dump when present on the API host, then runs catalog hygiene (prompts, weak hashes, bidirectional category backfill, attribute sanitize). Does not wipe or reimport the full catalog.",
|
||||
"admin.users.syncA1Company": "Company: {name}",
|
||||
"admin.users.syncA1Warning": "Requires descrybe_new.sql on the API server (scripts/seed/ or SEED_A1_MYSQL_DUMP) for dump category coverage. Without a dump, only DB hygiene runs. No mass reprocess.",
|
||||
"admin.users.syncA1Cancel": "Anuluj",
|
||||
"admin.users.syncA1Confirm": "Synchronizuj A1",
|
||||
"admin.users.noUsers": "Żaden użytkownik nie pasuje do tego filtra.",
|
||||
"admin.users.noCompanies": "Żadna firma nie pasuje do tego filtra.",
|
||||
"admin.users.assignRoleTitle": "Przypisz rolÄ™ personelu",
|
||||
@@ -2304,8 +2304,8 @@ export const pl: MessageDict = {
|
||||
"flash.admin.staffRoleUpdated": "Zaktualizowano rolÄ™ personelu dla {email}.",
|
||||
"flash.admin.staffRoleUnavailable": "Aktualizacje ról personelu nie są jeszcze dostępne na tym serwerze.",
|
||||
"flash.admin.catalogCloned": "Copied {source} into {dest}: {products} products, {categories} taxonomy categories, {mapped_with} with mapped category.",
|
||||
"flash.admin.fixA1Success": "Catalog repair finished for {name}: {prompts} prompts, {hashes} hashes, {categories} processed←mapped, {mapped_backfilled} mapped←processed. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.fixA1Error": "Naprawa katalogu dla {name} nie powiodła się.",
|
||||
"flash.admin.syncA1Success": "Synced A1 for {name}: dump_mapped {dump_mapped} ({dump_status}), prompts {prompts}, hashes {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.syncA1Error": "Synchronizacja A1 dla {name} nie powiodła się.",
|
||||
"flash.admin.cloneDestMissing": "No sandbox destination. Switch to Platform Demo (staff home), then clone again.",
|
||||
"flash.admin.planAssigned": "Przypisano plan do {name}.",
|
||||
"flash.admin.planAssignedShort": "Przypisano plan.",
|
||||
|
||||
@@ -812,14 +812,14 @@ export const pt: MessageDict = {
|
||||
"admin.users.cloneCatalogCancel": "Cancelar",
|
||||
"admin.users.cloneCatalogConfirm": "Copiar catálogo",
|
||||
"admin.users.cloneDestFallback": "a sua empresa sandbox",
|
||||
"admin.users.fixA1": "Reparar catálogo A1",
|
||||
"admin.users.fixA1Aria": "Reparar prompts de IA, categorias e hashes de enhance para {name}",
|
||||
"admin.users.fixA1Title": "Reparar catálogo da empresa",
|
||||
"admin.users.fixA1Desc": "Reaplica prompts de IA corrigidos, limpa hashes de enhance fracos e preenche categorias a partir de mapped_data.",
|
||||
"admin.users.fixA1Company": "Empresa: {name}",
|
||||
"admin.users.fixA1Warning": "Prefira Platform Demo ou uma empresa explÃcita. Não elimina feeds, mapeamentos ou produtos brutos. Protege as regras de substituição da coorte A1.",
|
||||
"admin.users.fixA1Cancel": "Cancelar",
|
||||
"admin.users.fixA1Confirm": "Reparar catálogo",
|
||||
"admin.users.syncA1": "Sincronizar A1",
|
||||
"admin.users.syncA1Aria": "Sync A1 categories from dump and repair catalog hygiene for {name}",
|
||||
"admin.users.syncA1Title": "Sincronizar catálogo A1",
|
||||
"admin.users.syncA1Desc": "Backfills mapped categories from the MySQL dump when present on the API host, then runs catalog hygiene (prompts, weak hashes, bidirectional category backfill, attribute sanitize). Does not wipe or reimport the full catalog.",
|
||||
"admin.users.syncA1Company": "Company: {name}",
|
||||
"admin.users.syncA1Warning": "Requires descrybe_new.sql on the API server (scripts/seed/ or SEED_A1_MYSQL_DUMP) for dump category coverage. Without a dump, only DB hygiene runs. No mass reprocess.",
|
||||
"admin.users.syncA1Cancel": "Cancelar",
|
||||
"admin.users.syncA1Confirm": "Sincronizar A1",
|
||||
"admin.users.noUsers": "Nenhum utilizador corresponde a este filtro.",
|
||||
"admin.users.noCompanies": "Nenhuma empresa corresponde a este filtro.",
|
||||
"admin.users.assignRoleTitle": "Atribuir função de equipa",
|
||||
@@ -2304,8 +2304,8 @@ export const pt: MessageDict = {
|
||||
"flash.admin.staffRoleUpdated": "Função de pessoal atualizada para {email}.",
|
||||
"flash.admin.staffRoleUnavailable": "As atualizações de função de pessoal ainda não estão disponÃveis neste servidor.",
|
||||
"flash.admin.catalogCloned": "Copied {source} into {dest}: {products} products, {categories} taxonomy categories, {mapped_with} with mapped category.",
|
||||
"flash.admin.fixA1Success": "Catalog repair finished for {name}: {prompts} prompts, {hashes} hashes, {categories} processed←mapped, {mapped_backfilled} mapped←processed. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.fixA1Error": "Falha na reparação do catálogo de {name}.",
|
||||
"flash.admin.syncA1Success": "Synced A1 for {name}: dump_mapped {dump_mapped} ({dump_status}), prompts {prompts}, hashes {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.syncA1Error": "Falha na sincronização A1 de {name}.",
|
||||
"flash.admin.cloneDestMissing": "No sandbox destination. Switch to Platform Demo (staff home), then clone again.",
|
||||
"flash.admin.planAssigned": "Plano atribuÃdo a {name}.",
|
||||
"flash.admin.planAssignedShort": "Plano atribuÃdo.",
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
/** Slovenian (sl) UI strings for admin Fix A1 — ready pack. Not registered in UI_LOCALES yet (avoid inventing locale switcher). */
|
||||
export const sl: MessageDict = {
|
||||
"admin.users.fixA1": "Popravi katalog A1",
|
||||
"admin.users.fixA1Aria": "Popravi AI pozive, kategorije in zgoÅ¡Äevalne vrednosti za {name}",
|
||||
"admin.users.fixA1Title": "Popravi katalog podjetja",
|
||||
"admin.users.fixA1Desc": "Ponovno uporabi popravljene AI pozive, poÄisti Å¡ibke enhance zgoÅ¡Äevalne vrednosti in dopolni kategorije iz mapped podatkov.",
|
||||
"admin.users.fixA1Company": "Podjetje: {name}",
|
||||
"admin.users.fixA1Warning": "Raje Platform Demo ali izrecno podjetje. Ne briÅ¡e feedov, mapiranj ali surovih izdelkov. Å Äiti pravila prepisovanja A1 kohorte.",
|
||||
"admin.users.fixA1Cancel": "PrekliÄi",
|
||||
"admin.users.fixA1Confirm": "Popravi katalog",
|
||||
"flash.admin.fixA1Success": "Popravilo kataloga za {name}: pozivi {prompts}, zgoščene {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Pokritost: {mapped_with}/{mapped_total} ({taxonomy} taksonomija).",
|
||||
"flash.admin.fixA1Error": "Popravilo kataloga za {name} ni uspelo.",
|
||||
"admin.users.syncA1": "Sinhroniziraj A1",
|
||||
"admin.users.syncA1Aria": "Sync A1 categories from dump and repair catalog hygiene for {name}",
|
||||
"admin.users.syncA1Title": "Sinhroniziraj katalog A1",
|
||||
"admin.users.syncA1Desc": "Backfills mapped categories from the MySQL dump when present on the API host, then runs catalog hygiene (prompts, weak hashes, bidirectional category backfill, attribute sanitize). Does not wipe or reimport the full catalog.",
|
||||
"admin.users.syncA1Company": "Company: {name}",
|
||||
"admin.users.syncA1Warning": "Requires descrybe_new.sql on the API server (scripts/seed/ or SEED_A1_MYSQL_DUMP) for dump category coverage. Without a dump, only DB hygiene runs. No mass reprocess.",
|
||||
"admin.users.syncA1Cancel": "Prekliči",
|
||||
"admin.users.syncA1Confirm": "Sinhroniziraj A1",
|
||||
"flash.admin.syncA1Success": "Synced A1 for {name}: dump_mapped {dump_mapped} ({dump_status}), prompts {prompts}, hashes {hashes}, processed←mapped {categories}, mapped←processed {mapped_backfilled}. Coverage: {mapped_with}/{mapped_total} ({taxonomy} taxonomy).",
|
||||
"flash.admin.syncA1Error": "Sinhronizacija A1 za {name} ni uspela.",
|
||||
"flash.admin.cloneDestMissing": "Ni ciljnega sandbox podjetja. Preklopite na Platform Demo, nato klonirajte.",
|
||||
};
|
||||
|
||||
+20
-20
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Focused check: admin Fix A1 i18n keys exist in every UI_LOCALES pack.
|
||||
/**
|
||||
* Focused check: admin Sync A1 i18n keys exist in every UI_LOCALES pack.
|
||||
*/
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
@@ -9,32 +9,32 @@ import { en } from "./messages/en.ts";
|
||||
import { loadAllMessages, messagesFor } from "./messages/catalog.ts";
|
||||
import { sl } from "./messages/sl.ts";
|
||||
|
||||
const FIX_A1_KEYS = [
|
||||
"admin.users.fixA1",
|
||||
"admin.users.fixA1Aria",
|
||||
"admin.users.fixA1Title",
|
||||
"admin.users.fixA1Desc",
|
||||
"admin.users.fixA1Company",
|
||||
"admin.users.fixA1Warning",
|
||||
"admin.users.fixA1Cancel",
|
||||
"admin.users.fixA1Confirm",
|
||||
"flash.admin.fixA1Success",
|
||||
"flash.admin.fixA1Error"
|
||||
const SYNC_A1_KEYS = [
|
||||
"admin.users.syncA1",
|
||||
"admin.users.syncA1Aria",
|
||||
"admin.users.syncA1Title",
|
||||
"admin.users.syncA1Desc",
|
||||
"admin.users.syncA1Company",
|
||||
"admin.users.syncA1Warning",
|
||||
"admin.users.syncA1Cancel",
|
||||
"admin.users.syncA1Confirm",
|
||||
"flash.admin.syncA1Success",
|
||||
"flash.admin.syncA1Error"
|
||||
] as const;
|
||||
|
||||
describe("admin Fix A1 i18n keys", () => {
|
||||
it("English defines every Fix A1 key", () => {
|
||||
for (const key of FIX_A1_KEYS) {
|
||||
describe("admin Sync A1 i18n keys", () => {
|
||||
it("English defines every Sync A1 key", () => {
|
||||
for (const key of SYNC_A1_KEYS) {
|
||||
assert.equal(typeof en[key], "string", key);
|
||||
assert.ok(en[key].trim().length > 0, key);
|
||||
}
|
||||
});
|
||||
|
||||
it("every registered UI locale has Fix A1 keys", async () => {
|
||||
it("every registered UI locale has Sync A1 keys", async () => {
|
||||
await loadAllMessages();
|
||||
for (const { code } of UI_LOCALES) {
|
||||
const pack = code === "en" ? en : messagesFor(code);
|
||||
for (const key of FIX_A1_KEYS) {
|
||||
for (const key of SYNC_A1_KEYS) {
|
||||
const value = pack[key];
|
||||
assert.equal(typeof value, "string", `${code}:${key}`);
|
||||
assert.ok(String(value).trim().length > 0, `${code}:${key}`);
|
||||
@@ -42,8 +42,8 @@ describe("admin Fix A1 i18n keys", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("Slovenian ready pack has Fix A1 keys (not in UI_LOCALES)", () => {
|
||||
for (const key of FIX_A1_KEYS) {
|
||||
it("Slovenian ready pack has Sync A1 keys (outside UI_LOCALES)", () => {
|
||||
for (const key of SYNC_A1_KEYS) {
|
||||
assert.equal(typeof sl[key], "string", key);
|
||||
assert.ok(sl[key].trim().length > 0, key);
|
||||
}
|
||||
Reference in New Issue
Block a user