subscribe our youtube channel popup

Using Custom Labels for Multi-Language LWC

Building applications that feel native to global audiences is an important part of modern business software. A lightweight and maintainable approach for localization on the Salesforce platform is to use Custom Labels together with Lightning Web Components (LWC). This pattern keeps translations in Salesforce’s translation tools while LWC code remains clean and language-skeptic. In this article we walk through a simple, practical implementation that demonstrates how to display translated UI strings on both a Home page and a Contact record page.

Business case

A support portal often serves customers across multiple countries. Maintaining separate components per language quickly becomes unmanageable. By using centralization UI text as Custom Labels and populating translations with the help of Translation Workbench, the same LWC adapts automatically to the currently logged-in user’s language. It will reduce maintenance, speed up updates and that will ensure consistency across pages. Normal users such as content managers or localization teams can update translations without touching code, which keeps responsibilities clear.

Post going through this blog above use case looks like as below:

Prerequisites

  • A Salesforce org with Translation Workbench enabled.
  • Spanish (Mexico) added as a supported language in the Translation Workbench.
  • Three Custom Labels created: Greeting, WelcomeMessage, ContactButton.
  • Translations added for Spanish (Mexico) for each label.
  • Basic familiarity with deploying LWCs and adding them to Lightning pages.

Creating the Custom Labels

Create the three labels from Setup → Custom Labels. Give each label a clear API name and a default value in the organization’s primary language. For this sample the defaults are:

  • Greeting → Hello
  • WelcomeMessage → Welcome, {0}!
  • ContactButton → Contact Support

Note the placeholder {0} inside WelcomeMessage; that token is replaced at runtime with the Contact’s name when the component runs on a record page. Keeping placeholders consistent across translations prevents runtime issues.

Adding translations (Translation Workbench)

Translation Workbench was enabled and Spanish (Mexico) was added as a supported language. When the Translate UI behaves differently across orgs, an alternative is to open each Custom Label record and use the ‘Translations’ action to add the Spanish (Mexico) text directly on the label record. The Spanish (Mexico) translations applied here are:

  • Greeting (es-MX) → Hola
  • WelcomeMessage (es-MX) → ¡Bienvenido, {0}!
  • ContactButton (es-MX) → Contactar Soporte

Make sure that placeholders such as {0} remain no change in the translated values. If any type of  translation is missed for a particular language, Salesforce will automatically display the default label value as a fallback that will make sure no user interaction fails in prod.

LWC implementation overview

The component is intentionally small and focuses on label usage plus a single field read. It is safe to place on both Home and Contact record pages. The code imports Custom Labels using the @salesforce/label/c.<APIName> syntax. When the component runs, Salesforce resolves the correct localized value for the logged-in user’s language; no runtime language switching logic is necessary in the component itself.

Detailed code walkthrough
The JavaScript imports core LWC modules and the UI Record API: LightningElement, api, wire, and getRecord. The three label imports map each label to a JavaScript constant, which are grouped into a LABELS object for tidy access in the template. The FIELDS array lists Contact.Name because the component reads the Contact name when placed on a Contact record page.

The @wire(getRecord, { recordId: ‘$recordId’, fields: FIELDS }) decorator populates contactName when a record context exists. The wired method checks for data.fields.Name to safely extract the value. When no record context is available (for example, on the Home page), contactName remains empty and the component falls back to the generic label usage.

The welcomeText getter performs a simple string replacement on the WELCOME_MESSAGE label value, replacing {0} with either the contact name or the fallback string ‘Customer’. This keeps the label itself language-focused while the component handles substitution logic.

The handleContact method acts as a placeholder for the action that should run when the Contact button is clicked. In this example it writes a message to the browser console, which makes it easy to demonstrate that the button is wired correctly; a console screenshot is included in the documentation to prove interaction.

Below are the code snippets that anyone can refer as an example:
The implementation uses the exact code listed below.

JavaScript (multiLangContact.js)

import {LightningElement,api,wire } from 'lwc';
import {getRecord} from 'lightning/uiRecordApi';

// Custom Labels
import GREETING from '@salesforce/label/c.Greeting';
import WELCOME_MESSAGE from '@salesforce/label/c.WelcomeMessage';
import CONTACT_BUTTON from '@salesforce/label/c.ContactButton';

const LABELS = {
    GREETING,
    WELCOME_MESSAGE,
    CONTACT_BUTTON
};

// fields to fetch (component intended to be placed on Contact record page)
const FIELDS = ['Contact.Name'];

export default class MultiLangContact extends LightningElement {
    @api recordId; // recordId will be provided when placed on a record page
    labels = LABELS;
    contactName = '';

    @wire(getRecord, { recordId: '$recordId', fields: FIELDS })
    wiredContact({ error, data }) {
        if (data && data.fields && data.fields.Name){
            this.contactName =data.fields.Name.value;
        } else {
            // fallback name if not available (e.g., not on a Contact record)
            this.contactName = '';
        }
    }

    // Replace simple {0} placeholder in the label with the contact name (or a fallback)
    get welcomeText() {
        const name=this.contactName || 'Customer';
        const template=this.labels.WELCOME_MESSAGE || '{0}';
        return template.replace('{0}',name);
    }

    handleContact() {
        // we can replace this with real navigation or logic (create case, open modal, etc.)
        console.log('Contact support clicked for:',this.contactName || this.recordId);
    }
}

HTML (multiLangContact.html)

<template>
    <div class="slds-p-around_medium">
        <h1>{labels.GREETING}</h1>
        <p>{welcomeText}</p>

        <lightning-button
            variant="brand"
            label={labels.CONTACT_BUTTON}
            onclick={handleContact}>
        </lightning-button>
    </div>
</template>

Meta XML (multiLangContact.js-meta.xml)

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns = "http://soap.sforce.com/2006/04/metadata">
    <apiVersion>64.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>

Deployment and page placement

After deploying the component, the bundle was added to two pages as examples: a Home page and a Contact record page. On the Home page the component renders the generic welcome label and shows “Welcome, Customer!” (or the translated string for Spanish (Mexico) users). On a Contact record page the component reads the contact name and renders a personalized greeting such as “Welcome, Contact.Name” or the translated equivalent.

Interaction proof and screenshots
By just clicking the Contact button that will trigger the handleContact method from our code, which logs a message to the browser console. The console output was captured as a screenshot and added below so stakeholders can verify the button wiring and behavior without require to reproduce the steps.

Once we clicked on button to verify is its working as expected added console logs in code so that any business logic can be implemented in future:

Troubleshooting any other issues

  • Missing translations: Always verify that any language (ex.Spanish (Mexico),etc) is enabled in Translation Workbench and that translations exist for each Custom Label. If a translation is not found Salesforce shows the default label value.
  • Wrong placeholders: a mismatch in placeholder tokens between default and translated values will produce incorrect welcome text. Keep placeholders exact.
  • Record context absent: when testing on the Home page the absence of a recordId causes the component to fall back to the generic greeting. Confirm the component is placed on a Contact record page to see personalized content.

Few Test Results of implementation of our logic mentioned above:

By English user on Contact Page:

On Home Page:

By Spanish User:

Best practices

  • Keep labels short and meaningful. Labels are easier to manage when concise.
  • Name labels consistently and with a clear prefix to reduce collision risk.
  • Use placeholders for variable content and centralize substitution in component code.
  • Store labels and translations in source control and include translations in deployments to keep environments in sync.
  • For larger localization efforts, consider translation management tools or a translation memory to keep text consistent across releases.

Conclusion

Using Custom Labels with LWC provides a clean separation of localization from component logic, enabling both development and localization teams to work independently. The simple component shared here demonstrates how a single LWC can handle both a Home page greeting and a Contact-specific personalized message, while Translation Workbench manages language variations. This pattern scales well as more languages are added and keeps translation ownership where it belongs with content teams. Happy Implementing 🙂

Satyam parasa
Satyam parasa

Satyam Parasa is a Salesforce and Mobile application developer. Passionate about learning new technologies, he is the founder of Flutterant.com, where he shares his knowledge and insights.

Articles: 54

Leave a Reply

Your email address will not be published. Required fields are marked *