diff --git a/frontend/editor/public/locales/en-US/translation.toml b/frontend/editor/public/locales/en-US/translation.toml index 4af1be3359..8271d66dfc 100644 --- a/frontend/editor/public/locales/en-US/translation.toml +++ b/frontend/editor/public/locales/en-US/translation.toml @@ -3001,6 +3001,293 @@ summary_one = "Ran 1 tool" summary_other = "Ran {{count}} tools" unknownTool = "Unknown tool" +[classification.families] +correspondence = "Correspondence" +education = "Education" +engineering = "Engineering" +finance = "Financial" +forms = "Forms" +government = "Government" +health = "Medical" +hr = "HR" +legal = "Legal" +operations = "Operations" +projects = "Projects" +property = "Property" +reports = "Reports" +sales = "Marketing" +travel = "Travel" + +[classification.labels] +academic-record = "Academic record" +action-plan = "Action plan" +addendum = "Addendum" +advertisement = "Advertisement" +affidavit = "Affidavit" +agenda = "Agenda" +amendment = "Amendment" +analytics-report = "Analytics report" +announcement = "Announcement" +annual-report = "Annual report" +api-documentation = "API documentation" +application-form = "Application form" +appraisal-report = "Appraisal report" +architecture-document = "Architecture document" +articles-of-incorporation = "Articles of incorporation" +assignment-brief = "Assignment brief" +audit-report = "Audit report" +balance-sheet = "Balance sheet" +bank-statement = "Bank statement" +benefits-summary = "Benefits summary" +bill-of-lading = "Bill of lading" +bill-of-materials = "Bill of materials" +blueprint = "Blueprint" +board-report = "Board report" +board-resolution = "Board resolution" +booking-confirmation = "Booking confirmation" +brochure = "Brochure" +budget = "Budget" +business-plan = "Business plan" +business-proposal = "Business proposal" +bylaws = "Bylaws" +campaign-brief = "Campaign brief" +case-study = "Case study" +cash-flow-statement = "Cash flow statement" +catalog = "Catalog" +cease-and-desist = "Cease and desist" +certificate = "Certificate" +certificate-of-completion = "Certificate of completion" +change-log = "Change log" +checklist = "Checklist" +claim-form = "Claim form" +closing-statement = "Closing statement" +complaint-letter = "Complaint letter" +compliance-document = "Compliance document" +confirmation-letter = "Confirmation letter" +consent-form = "Consent form" +contract = "Contract" +course-syllabus = "Course syllabus" +court-filing = "Court filing" +cover-letter = "Cover letter" +credit-note = "Credit note" +customs-declaration = "Customs declaration" +customs-form = "Customs form" +cv = "CV" +datasheet = "Datasheet" +debit-note = "Debit note" +deed = "Deed" +delivery-note = "Delivery note" +demand-letter = "Demand letter" +design-document = "Design document" +diploma = "Diploma" +discharge-summary = "Discharge summary" +dissertation = "Dissertation" +donation-receipt = "Donation receipt" +dunning-letter = "Dunning letter" +email-thread = "Email thread" +employee-handbook = "Employee handbook" +employment-contract = "Employment contract" +estimate = "Estimate" +event-agenda = "Event agenda" +event-program = "Event program" +eviction-notice = "Eviction notice" +exam-paper = "Exam paper" +expense-report = "Expense report" +expense-summary = "Expense summary" +explanation-of-benefits = "Explanation of benefits" +fact-sheet = "Fact sheet" +faq-document = "FAQ document" +feasibility-study = "Feasibility study" +feedback-form = "Feedback form" +financial-forecast = "Financial forecast" +financial-statement = "Financial statement" +floor-plan = "Floor plan" +flyer = "Flyer" +form = "Form" +franchise-agreement = "Franchise agreement" +freight-document = "Freight document" +gift-certificate = "Gift certificate" +glossary = "Glossary" +government-notice = "Government notice" +grade-report = "Grade report" +grant-agreement = "Grant agreement" +grant-application = "Grant application" +hoa-document = "HOA document" +home-inspection-report = "Home inspection report" +hr-memo = "HR memo" +hr-policy = "HR policy" +immigration-document = "Immigration document" +immunization-record = "Immunization record" +incident-report = "Incident report" +income-statement = "Income statement" +index = "Index" +inspection-report = "Inspection report" +insurance-certificate = "Insurance certificate" +insurance-claim = "Insurance claim" +insurance-policy = "Insurance policy" +intake-form = "Intake form" +inventory-list = "Inventory list" +investment-summary = "Investment summary" +invitation = "Invitation" +invoice = "Invoice" +itinerary = "Itinerary" +job-application = "Job application" +job-description = "Job description" +lab-report = "Lab report" +lease-agreement = "Lease agreement" +leave-request = "Leave request" +legal-brief = "Legal brief" +legal-filing = "Legal filing" +legal-notice = "Legal notice" +legal-opinion = "Legal opinion" +lesson-plan = "Lesson plan" +letter = "Letter" +letter-of-intent = "Letter of intent" +license = "License" +license-agreement = "License agreement" +loan-agreement = "Loan agreement" +loan-document = "Loan document" +maintenance-log = "Maintenance log" +manual = "Manual" +market-research = "Market research" +marketing-plan = "Marketing plan" +media-kit = "Media kit" +medical-invoice = "Medical invoice" +medical-report = "Medical report" +meeting-agenda = "Meeting agenda" +meeting-minutes = "Meeting minutes" +meeting-notes = "Meeting notes" +membership-document = "Membership document" +memo = "Memo" +memorandum-of-understanding = "Memorandum of understanding" +mortgage-document = "Mortgage document" +nda = "NDA" +newsletter = "Newsletter" +non-compete-agreement = "Non-compete agreement" +notice = "Notice" +offer-letter = "Offer letter" +onboarding-document = "Onboarding document" +order-confirmation = "Order confirmation" +order-form = "Order form" +organization-chart = "Organization chart" +packing-slip = "Packing slip" +partnership-agreement = "Partnership agreement" +patent = "Patent" +pathology-report = "Pathology report" +payment-reminder = "Payment reminder" +payroll-document = "Payroll document" +payslip = "Payslip" +performance-review = "Performance review" +permit = "Permit" +petition = "Petition" +pitch-deck = "Pitch deck" +power-of-attorney = "Power of attorney" +prescription = "Prescription" +presentation = "Presentation" +press-release = "Press release" +price-list = "Price list" +pricing-sheet = "Pricing sheet" +privacy-policy = "Privacy policy" +product-sheet = "Product sheet" +proforma-invoice = "Proforma invoice" +progress-report = "Progress report" +project-charter = "Project charter" +project-plan = "Project plan" +promotional-material = "Promotional material" +property-listing = "Property listing" +proposal = "Proposal" +public-notice = "Public notice" +purchase-agreement = "Purchase agreement" +purchase-order = "Purchase order" +quality-report = "Quality report" +quarterly-report = "Quarterly report" +questionnaire = "Questionnaire" +quick-start-guide = "Quick start guide" +quote = "Quote" +radiology-report = "Radiology report" +receipt = "Receipt" +recommendation-letter = "Recommendation letter" +reference-letter = "Reference letter" +referral-letter = "Referral letter" +registration-confirmation = "Registration confirmation" +registration-form = "Registration form" +regulatory-filing = "Regulatory filing" +release-notes = "Release notes" +remittance-advice = "Remittance advice" +rental-agreement = "Rental agreement" +report = "Report" +request-for-proposal = "Request for proposal" +request-for-quotation = "Request for quotation" +requirements-document = "Requirements document" +research-abstract = "Research abstract" +research-paper = "Research paper" +reservation = "Reservation" +resignation-letter = "Resignation letter" +resume = "Resume" +retrospective = "Retrospective" +return-authorization = "Return authorization" +risk-assessment = "Risk assessment" +roadmap = "Roadmap" +safety-data-sheet = "Safety data sheet" +safety-procedure = "Safety procedure" +sales-proposal = "Sales proposal" +sales-report = "Sales report" +schematic = "Schematic" +scope-of-work = "Scope of work" +service-agreement = "Service agreement" +service-report = "Service report" +settlement-agreement = "Settlement agreement" +shareholder-agreement = "Shareholder agreement" +shipping-confirmation = "Shipping confirmation" +specification = "Specification" +sponsorship-agreement = "Sponsorship agreement" +standard-operating-procedure = "Standard operating procedure" +statement-of-account = "Statement of account" +statement-of-work = "Statement of work" +status-report = "Status report" +stock-report = "Stock report" +study-guide = "Study guide" +subpoena = "Subpoena" +subscription-confirmation = "Subscription confirmation" +supply-order = "Supply order" +survey-form = "Survey form" +survey-results = "Survey results" +sustainability-report = "Sustainability report" +table-of-contents = "Table of contents" +tax-form = "Tax form" +tax-return = "Tax return" +tax-statement = "Tax statement" +technical-drawing = "Technical drawing" +technical-specification = "Technical specification" +tenancy-agreement = "Tenancy agreement" +tender-document = "Tender document" +termination-letter = "Termination letter" +terms-and-conditions = "Terms and conditions" +terms-of-service = "Terms of service" +test-plan = "Test plan" +test-report = "Test report" +thesis = "Thesis" +ticket = "Ticket" +timeline = "Timeline" +timesheet = "Timesheet" +title-document = "Title document" +training-material = "Training material" +transcript = "Transcript" +travel-itinerary = "Travel itinerary" +trust-document = "Trust document" +user-guide = "User guide" +utility-bill = "Utility bill" +vendor-agreement = "Vendor agreement" +visa-document = "Visa document" +waiver = "Waiver" +warehouse-receipt = "Warehouse receipt" +warranty-document = "Warranty document" +waybill = "Waybill" +white-paper = "White paper" +will = "Will" +work-instruction = "Work instruction" +work-order = "Work order" + [cloudBadge] tooltip = "This operation will use your cloud credits" diff --git a/frontend/editor/src/portal/components/policies/ClassificationLabelsSection.tsx b/frontend/editor/src/portal/components/policies/ClassificationLabelsSection.tsx index 7a21cae2b7..4b3fae7652 100644 --- a/frontend/editor/src/portal/components/policies/ClassificationLabelsSection.tsx +++ b/frontend/editor/src/portal/components/policies/ClassificationLabelsSection.tsx @@ -61,7 +61,7 @@ export function ClassificationLabelsSection() { )} - {family.name} + {t(`classification.families.${family.id}`, family.name)} } diff --git a/frontend/editor/src/proprietary/components/policies/ClassificationCategoryManager.tsx b/frontend/editor/src/proprietary/components/policies/ClassificationCategoryManager.tsx index 143e344f82..bc29f74bae 100644 --- a/frontend/editor/src/proprietary/components/policies/ClassificationCategoryManager.tsx +++ b/frontend/editor/src/proprietary/components/policies/ClassificationCategoryManager.tsx @@ -40,7 +40,9 @@ export function ClassificationCategoryManager({ - {category.name} + + {t(`classification.families.${category.id}`, category.name)} + {count !== undefined && ( {count} )} diff --git a/frontend/editor/src/proprietary/components/shared/fileSidebarGroupingLogic.ts b/frontend/editor/src/proprietary/components/shared/fileSidebarGroupingLogic.ts index 5b4b30ce33..d8b06f12f4 100644 --- a/frontend/editor/src/proprietary/components/shared/fileSidebarGroupingLogic.ts +++ b/frontend/editor/src/proprietary/components/shared/fileSidebarGroupingLogic.ts @@ -56,7 +56,7 @@ export function buildLabelGroups( if (members.length === 0) continue; visible.push({ id: `category:${category.id}`, - label: category.name, + label: t(`classification.families.${category.id}`, category.name), icon: category.icon, stubs: members, defaultExpanded: false, diff --git a/frontend/editor/src/proprietary/data/classificationLabels.i18n.test.ts b/frontend/editor/src/proprietary/data/classificationLabels.i18n.test.ts new file mode 100644 index 0000000000..842a7127e7 --- /dev/null +++ b/frontend/editor/src/proprietary/data/classificationLabels.i18n.test.ts @@ -0,0 +1,58 @@ +import fs from "fs"; +import path from "path"; +import { describe, it, expect } from "vitest"; +import { parse } from "smol-toml"; +import { + DEFAULT_CLASSIFICATION_LABELS, + LABEL_FAMILIES, +} from "@app/data/classificationLabels"; + +// Label and family names are rendered through `classification.labels.` / +// `classification.families.`, with the built-in English name as the fallback. +// A fallback renders fine but is never translated (and logs a missingKey), so a +// label added to classificationLabels.json without its en-US key silently ships +// English to every locale. This guards that the en-US vocabulary stays complete. + +const EN_US_TRANSLATIONS = path.join( + __dirname, + "../../../public/locales/en-US/translation.toml", +); + +function readSection(section: string): Record { + const parsed = parse(fs.readFileSync(EN_US_TRANSLATIONS, "utf8")) as { + classification?: Record>; + }; + return parsed.classification?.[section] ?? {}; +} + +describe("classification vocabulary (en-US coverage)", () => { + const labels = readSection("labels"); + const families = readSection("families"); + + it("has an en-US key for every label id, matching its built-in name", () => { + for (const label of DEFAULT_CLASSIFICATION_LABELS) { + expect( + labels[label.id], + `en-US missing classification.labels.${label.id}`, + ).toBe(label.name); + } + }); + + it("has an en-US key for every family id, matching its built-in name", () => { + for (const family of LABEL_FAMILIES) { + expect( + families[family.id], + `en-US missing classification.families.${family.id}`, + ).toBe(family.name); + } + }); + + it("has no en-US keys for labels or families that no longer exist", () => { + const labelIds = new Set(DEFAULT_CLASSIFICATION_LABELS.map((l) => l.id)); + const familyIds = new Set(LABEL_FAMILIES.map((f) => f.id)); + expect(Object.keys(labels).filter((id) => !labelIds.has(id))).toEqual([]); + expect(Object.keys(families).filter((id) => !familyIds.has(id))).toEqual( + [], + ); + }); +});