What You'll Learn
How Custom Labels work under the hood, when they become unmanageable, strategies for naming conventions and namespace hygiene, and how Translation Workbench fits into enterprise-grade multi-language deployments.
Why Custom Labels Deserve Architectural Attention
Custom Labels are often the last thing an architect thinks about and the first thing that breaks during a global rollout. They start as a convenient way to externalise strings — error messages, button text, email subjects — but grow into a sprawling metadata layer that nobody owns, nobody documents, and everybody depends on.
At the 500+ label mark, teams start hitting real problems: naming collisions, stale labels that no component uses, duplicated values with slightly different wordings, and Translation Workbench exports that are 80% redundant. A disciplined approach from day one prevents months of painful cleanup.
How Custom Labels Are Stored and Resolved
Each Custom Label is an XML metadata file inside the labels/ directory, collected into a single CustomLabels.labels-meta.xml file in SFDX projects. At runtime, Salesforce resolves labels through a locale stack:
- User's personal language setting
- Profile default language
- Org-level default language
- Fall back to the label's master value if no translation exists
The resolution happens server-side for Apex and Visualforce, and client-side for LWC via the @salesforce/label import.
// LWC — importing a custom label
import SAVE_BUTTON from '@salesforce/label/c.Save_Button_Label';
import ERROR_REQUIRED from '@salesforce/label/c.Validation_Required_Field';
export default class MyForm extends LightningElement {
label = { saveButton: SAVE_BUTTON, errorRequired: ERROR_REQUIRED };
}
// Apex — using a label
String msg = System.Label.Account_Save_Success;
// Visualforce
<apex:outputText value="{!$Label.c.Account_Save_Success}" />Naming Conventions That Scale
The most impactful decision you make about Custom Labels is the naming scheme. A flat namespace ("ErrorMessage", "SaveButton") degrades immediately. A hierarchical scheme using underscores as separators survives a 2,000-label org:
// Pattern: <Domain>_<Object>_<Context>_<Type>
// Good
Account_Save_Success_Toast
Account_Delete_Confirm_Modal_Body
Quote_LineItem_Tax_Tooltip
Validation_Required_Field_Error
// Bad
SaveSuccess // no domain
acct_err_1 // cryptic abbreviation
Button_Label_New // backwards hierarchy
SuccessMessage // reused across 40 featuresAdopt a governance rule: no label gets merged without a Jira ticket referencing the feature it belongs to. This creates an audit trail when labels need to be retired.
Validation_ for field/input errors, Toast_ for notification messages, Modal_ for dialog content, Field_Help_ for help text. New contributors should know where their label belongs before they create it.
Translation Workbench Architecture
Translation Workbench (TWB) extends Custom Labels to support multiple languages. It also handles field labels, picklist values, page layouts, and custom object names — not just labels. Understanding the full scope matters because translating labels in isolation misses half the user-facing text.
The translation pipeline has three stages:
- Enable language: From Setup > Translation Language Settings. This creates the language record and enables TWB exports for that locale.
- Export for translation: Metadata API exports a ZIP with language-specific XML files. Third-party translation vendors receive these XML files.
- Import translated content: Import the translated ZIP back, or use the UI to paste values directly for small volumes.
<!-- CustomLabels.labels-meta.xml structure -->
<CustomLabels xmlns="http://soap.sforce.com/2006/04/metadata">
<labels>
<fullName>Account_Save_Success_Toast</fullName>
<categories>Account,Toast</categories>
<language>en_US</language>
<protected>false</protected>
<shortDescription>Toast shown after account save</shortDescription>
<value>Account saved successfully.</value>
</labels>
</CustomLabels>Translation at Scale: Governance Patterns
Global deployments with 5+ active languages create workflow complexity. The labels added in a summer release need translation before go-live, which means translation vendors need 2-3 weeks lead time, which means the export must happen before UAT even finishes. This creates pressure to freeze labels early.
Proven patterns for managing this:
- Label freeze window: Declare a "label freeze" date 4 weeks before release go-live. New features after that date either use existing labels or defer to the next release.
- Translation memory: Use a CAT (computer-assisted translation) tool like Crowdin or Phrase that maintains a TM database. Near-duplicate labels cost a fraction of full translation cost.
- English-first fallback: For power-user or admin-facing labels that are not customer-visible, English fallback is acceptable. Document this policy so translators don't waste effort.
- Automated delta detection: Script a comparison between the current labels export and the last translated export to identify only new/changed labels. This makes translation faster and cheaper.
Labels in Managed Packages
If you are building a managed package (1GP or 2GP), Custom Labels live in the package namespace. Subscribers see them as namespace__LabelName. This has important implications:
- Subscribers cannot directly edit your package labels. They can override them by creating a label with the same name in their default namespace.
- Translation Workbench translations in your packaging org deploy with the package — subscribers do not need to re-translate.
- In 2GP, labels can be declared as public or protected. Protected labels cannot be overridden by subscribers.
Cleaning Up: Label Retirement at Scale
Deleting a Custom Label is a destructive metadata operation that cannot be rolled back from Setup. Before deletion, confirm that no Apex, LWC, Flow, or Visualforce references the label. The safest approach:
- Search the full codebase (including Flow metadata XML) for the label API name.
- Remove all references in a single PR/changeset.
- Deploy the reference-removal to production.
- Delete the label from the org (via Metadata API delete or Setup UI).
- Remove from source control and deploy the deletion manifest.
Never delete a label and remove its references in the same deployment — the deployment order is not guaranteed, and a timing window can cause a null reference error in production.
Key Takeaways
- Custom Labels are global metadata — naming conventions and ownership matter from day one.
- Use a hierarchical naming scheme: Domain_Object_Context_Type.
- Translation Workbench translates more than labels: it also handles picklists, page layouts, and object names.
- Plan a label freeze window 4 weeks before go-live to give vendors adequate lead time.
- In managed packages, subscribers can override non-protected labels — use this as a customisation mechanism.
- Label deletion is irreversible — remove references before removing the label, never simultaneously.
Check Your Understanding
1. In LWC, what happens to Custom Labels that are imported but never referenced in the template or controller?
2. You need to retire a Custom Label that is referenced in three LWC components. What is the correct sequence?
3. Which Translation Workbench capability is NOT available for Custom Labels specifically?
Discussion & Feedback