Cometchat I18n
cometchat/cometchat-skills
Localize a CometChat integration — set the UI Kit language, register custom/overridden translations, handle RTL, and never leak a raw localization key into the UI.
MUST activate to localize / internationalize a uiBundles//src/ project (React or Angular): extract hardcoded user-facing strings into Custom Labels, wire a runtime i18n library over the Platform SDK…
$ npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-localize -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install forcedotcom/sf-skills experience-ui-bundle-localize --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/experience-ui-bundle-localize .claude/skills/experience-ui-bundle-localize && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "experience-ui-bundle-localize" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/experience-ui-bundle-localize into .claude/skills/experience-ui-bundle-localize/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "experience-ui-bundle-localize", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/forcedotcom/sf-skills/tree/main/skills/experience-ui-bundle-localizeType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-localize -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install forcedotcom/sf-skills experience-ui-bundle-localize --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/experience-ui-bundle-localize .agents/skills/experience-ui-bundle-localize && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "experience-ui-bundle-localize" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/experience-ui-bundle-localize into .agents/skills/experience-ui-bundle-localize/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "experience-ui-bundle-localize", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-localize -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install forcedotcom/sf-skills experience-ui-bundle-localize --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/experience-ui-bundle-localize .cursor/skills/experience-ui-bundle-localize && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "experience-ui-bundle-localize" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/experience-ui-bundle-localize into .cursor/skills/experience-ui-bundle-localize/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "experience-ui-bundle-localize", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/forcedotcom/sf-skills.git --path skills/experience-ui-bundle-localize--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-localize -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install forcedotcom/sf-skills experience-ui-bundle-localize --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/experience-ui-bundle-localize .gemini/skills/experience-ui-bundle-localize && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "experience-ui-bundle-localize" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/experience-ui-bundle-localize into .gemini/skills/experience-ui-bundle-localize/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "experience-ui-bundle-localize", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install forcedotcom/sf-skills experience-ui-bundle-localizeInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-localize -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/experience-ui-bundle-localize .github/skills/experience-ui-bundle-localize && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "experience-ui-bundle-localize" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/experience-ui-bundle-localize into .github/skills/experience-ui-bundle-localize/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "experience-ui-bundle-localize", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-localize -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install forcedotcom/sf-skills experience-ui-bundle-localize --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/experience-ui-bundle-localize .opencode/skills/experience-ui-bundle-localize && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "experience-ui-bundle-localize" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/experience-ui-bundle-localize into .opencode/skills/experience-ui-bundle-localize/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "experience-ui-bundle-localize", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
experience-ui-bundle-localizeMUST activate to localize / internationalize a uiBundles//src/ project (React or Angular): extract hardcoded user-facing strings into Custom Labels, wire a runtime i18n library over the Platform SDK…
Experience UI Bundle Localize is an agent skill from forcedotcom/sf-skills. MUST activate to localize / internationalize a uiBundles//src/ project (React or Angular): extract hardcoded user-facing strings into Custom Labels, wire a runtime i18n library over the Platform SDK backend, add labels for another language, or troubleshoot label rendering across locales. Triggers: user-facing string literals in component files, a CustomLabels.labels-meta.xml, a src/i18n/ directory or label-manifest.ts, translation call sites, or requests to 'translate / localize / internationalize / support…
Its SKILL.md is about 5.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 23 other files, including scripts and reference files (for example `references/angular/check-i18n-wired.sh`, `references/angular/i18n-setup.md` and `references/angular/interpolation.md`).
It sits in Frontend & Design, covering Translation, Internationalization and CRM management. It works with Salesforce, React and Angular. The repository describes itself as: Salesforce's curated collection of agent skills for building applications. Optimized for Agentforce Vibes, compatible with all AI tools. The licence is Apache-2.0.
Read from SKILL.md and the folder at commit 3c15867. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 3 files in scripts/ (Shell, from the files we listed), which the agent can run.
Shell commands in SKILL.md call:
bashsfnpmFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npm, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Experience UI Bundle Localize loads about 5.8k tokens when it runs, and up to ~35k if it reads all its reference files. Until then it costs about 264 tokens; SKILL.md has 2,804 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from forcedotcom/sf-skills at commit 3c15867, republished under its Apache-2.0 licence (© forcedotcom). 2,804 words, ~5,811 tokens.
.claude/skills/experience-ui-bundle-localize/SKILL.md (or your agent's skills folder). This skill also uses 18 other files; get the full folder from GitHub.Localize a UI Bundle: extract user-facing strings into Salesforce Custom Labels, wire a runtime i18n library over the Platform SDK backend, and verify labels across locales.
This file is the framework-neutral workflow + guardrail spine. The framework-specific detail — which i18n library, the translation call convention, the files scanned, the wiring shape, and the depth docs — lives in a per-framework reference.
A UI Bundle can't use compile-time label imports the way LWC does (@salesforce/label/*
resolves inside the platform's compiler, which your standalone bundle doesn't go through).
Instead, your app fetches labels at runtime through the Salesforce GraphQL UI API and
hands them to a standard i18n library to render. The Platform SDK provides the runtime
plumbing: a detector that reads the user's language, a backend that fetches labels over
GraphQL, and a context fetch. You write two thin files — a short init that wires the SDK
pieces into your i18n library, and a manifest listing which labels your app uses — then
author the labels themselves as Salesforce Custom Labels metadata. The exact library and
call convention are framework-specific; see your framework reference.
| The task is… | Go to |
|---|---|
| Bundle doesn't exist yet | experience-ui-bundle-frontend-generate skill |
| Deploying the app with its labels | experience-ui-bundle-deploy skill |
Configuring site languages or sfdc_cms__languageSettings | experience-ui-bundle-site-generate skill |
| Localizing an existing bundle | Determine the framework (below), then the workflow |
Determine the framework. It is normally already decided by the calling context — passed down by the coordinator skill that invoked this one, or stated in the user's request. Use that.
The frameworks this skill supports are exactly the reference folders under
<SKILL_DIR>/references/, each containing a localize.md (so react →
<SKILL_DIR>/references/react/localize.md). This is the single source of truth — adding a
framework means adding a reference folder, nothing here changes.
If the framework is known — open <SKILL_DIR>/references/<framework>/localize.md and
keep it alongside this spine. It supplies the library, the call convention, the files to
scan, and the wiring code.
If it is unknown (a standalone run where nobody said which) — run the deterministic detector on the app / uiBundle root before asking anyone:
bash "<SKILL_DIR>/scripts/detect-framework.sh" "<app-or-uiBundle-root>"It combines an angular.json at/above the root, @angular/core / react in any
non-node_modules package.json, and source-file signatures, then prints one token and
sets a matching exit code:
react or angular (exit 0) → use that framework. Do not ask the user — the
detection is deterministic. Open <SKILL_DIR>/references/<framework>/localize.md.ambiguous (exit 2) → both frameworks are present. List <SKILL_DIR>/references/ and ask
the user which one to localize. If they name a framework with no matching reference folder,
it is not supported here — stop.unknown (exit 3) → no supported framework detected. Terminate the workflow. Do not
guess and do not proceed: report that neither React nor Angular signals were found in the
bundle, so localization cannot continue, and stop here.Throughout the steps below, <framework> means the folder chosen here. The deterministic
check scripts split by coupling:
<SKILL_DIR>/scripts/ — detect-framework.sh (the Step-0
detector above), check-org-api-version.sh and detect-bundle-type.sh (pure org/metadata
checks), and check-manifest-registered.sh (agnostic skeleton; it takes --framework <framework> to select the call-site grammar).<SKILL_DIR>/references/<framework>/ — check-i18n-wired.sh
(its manifest-into-backend detection is i18n-library-shaped, so each framework ships its own).| # | Requirement | Verify | If missing |
|---|---|---|---|
| 1 | It's a uiBundles/*/src/ project (React or Angular) | Project structure matches | Not a UI Bundle → route to the correct skill |
| 2 | Platform SDK, UI Bundle, and build-plugin siblings installed and aligned (≥11.49.3) | package.json in the UI bundle dir | Tell user to align and upgrade them; cannot proceed |
| 3 | You can identify where the app mounts | Read the entry file (see the framework reference) | No clear mount point → ask user to point it out |
| 4 | Target org actually supports API v68.0+ (runtime label GraphQL for UI Bundles ships in Release 264) | Run the runtime org-release check below | Org's max API version is below v68.0 (Release 262 or older) → cannot proceed; retarget a Release 264+ org or upgrade the org |
| 5 | The bundle is authenticated B2E or the request/context explicitly identifies a B2C site, not B2B | Run the bundle-type detection below and use the request/context for site product identity | Explicit B2B → reject; site type not explicit → ask the user and stop until confirmed; B2C also requires precondition 6 |
| 6 | For B2C only, an admin has enabled GraphQLApiOrgPrefForGuestUsers | Ask the admin to confirm the org preference is already enabled | Do not enable it; explain that guest GraphQL returns HTTP 403 without it and stop (dependency: W-23854208) |
Runtime org-release check (precondition 4). The platform.labels GraphQL path that resolves labels at runtime for UI Bundles ships in Salesforce Release 264 (API v68.0 or higher). A sourceApiVersion in sfdx-project.json records what you declared, not what the org supports, so a newer CLI pointed at an older org can pass a static file check and then fail at runtime. Query the org's actual maximum API version before wiring anything:
bash <SKILL_DIR>/scripts/check-org-api-version.sh <org-alias-or-username>Exit 0 → the org supports v68.0+, proceed. Exit 1 → the org is too old or unreachable; do not write i18n wiring or labels, report the version mismatch to the user and stop. (sf api request rest inside the script keeps authentication at the CLI transport layer, so no access token enters context.)
Bundle-type detection (precondition 5). The bundle's type decides which localization branch applies. It is framework-agnostic (pure Salesforce metadata). Pass the full path to the bundle dir; the script derives the metadata root from it, so the current directory does not matter:
bash <SKILL_DIR>/scripts/detect-bundle-type.sh <path-to-uiBundles/<name>/ dir>Act on the exit-code contract: 0 → authenticated app (B2E or in-core internal), use the B2E branch; 10 → bound public site app-container candidate, meaning metadata proves site binding and guest access but not B2C versus B2B; 11 → bound non-public/unsupported site, stop; 12 → both CustomApplication and one site binding exist, ask which runtime context is the localization target; 13 → multiple matching Experience site bindings, show the reported site names and ask which site/runtime context is the target; 2 → unbound/unknown, report the script output and stop rather than guessing.
For exit 10, route by explicit request/context: if it says B2C, confirm precondition 6 and use the B2C branch; if it says B2B, reject it; if product type is not explicit, ask the user whether the site is B2C or B2B and stop until confirmed. For exits 12 and 13, require the user to choose the runtime context (and site for exit 13), then apply that branch's fallback and prerequisites. Never infer B2C from DigitalExperienceConfig, appSpace, appContainer, or AUTHENTICATED_WITH_PUBLIC_ACCESS_ENABLED; the authentication value means guest access is enabled.
For B2C, only an org admin may enable GraphQLApiOrgPrefForGuestUsers; never provision or change it. Without it, guest label requests return HTTP 403. Track availability through W-23854208.
If a precondition isn't met, stop: report the specific block to the user and record a plan item to return once it's resolved. Do not add i18n wiring or TODO markers to a B2B or unknown bundle.
Each step has a completion criterion and a confirm-before-continue pause. Framework
specifics (file extensions, the translation call, the install, the init code) come from
<SKILL_DIR>/references/<framework>/localize.md.
Goal: Scan the framework's component files for user-facing hardcoded strings. (The framework reference names the file extensions to scan.)
What to scan:
Welcome in a heading → candidateplaceholder="Enter name" → candidatearia-label, aria-describedby, alt → candidate (a screen-reader user hears these, so they must localize too)What to skip:
data-* attributes (machine-readable)data-testid, id attributes)Action:
src/ directory for the framework's component filesCompletion criterion: Developer confirms the list (or edits it to remove false positives).
Pause: "I found N user-facing strings across M components. Here's the list: [show file:line + string]. Look right? [confirm / edit the list / skip some]"
Goal: For each confirmed string, add a Custom Label and replace the literal with a translation call.
Action for each string:
<Context>_<Role> (e.g., "Welcome" → Welcome_Text, "Save" → Save_Button, "Failed to save" → Save_Failed_Message). Follow naming: PascalCase words, underscores between parts, descriptive enough to be unique.force-app/main/default/labels/CustomLabels.labels-meta.xml:<labels>
<fullName>Welcome_Text</fullName>
<language>en_US</language>
<protected>false</protected>
<shortDescription>Welcome banner heading</shortDescription>
<value>Welcome</value>
</labels>references/common/label-xml.md)Completion criterion:
Every confirmed string has both a CustomLabels entry and a translation call in its original location.
Pause: "For each string I'll add a Custom Label and replace the literal with a translation call. Here are the proposed keys: [show string → namespace:Key mapping]. Apply these edits? [y / review each]"
Goal: Add each key to the label manifest so the i18n runtime knows to fetch it.
Action:
src/i18n/label-manifest.ts:export const labelManifest = [
"c:Welcome_Text",
"c:Save_Button",
"c:Save_Failed_Message",
];Completion criterion:
Run check-manifest-registered.sh from the UI bundle dir (it scans src/ relative to the current directory) and report any errors it returns. It owns the deterministic inspection: it cross-checks every translation call site against the manifest and treats a missing label-manifest.ts (when call sites exist) as a failure. A key that's called but not registered renders as its own literal name at runtime with no error, the silent-fail trap this guards.
cd <path-to-uiBundles/<name>/ dir> # scripts scan src/ relative to here
bash <SKILL_DIR>/scripts/check-manifest-registered.sh --framework <framework>Branch on the exit code: 0, every key is registered (or there are no call sites to gate), proceed. 1, the manifest is missing or the listed keys aren't in it; scaffold or add them (Step 4 scaffolds the file) and re-run. 64, usage error, the source dir doesn't exist (wrong cwd or bad argument); this is not a "keys missing" result, do not scaffold or register, fix the path and re-run.
Pause: "Added N entries to label-manifest.ts. check-manifest-registered.sh passed: [confirm]."
Goal: Ensure the i18n wiring exists; scaffold it if the app has no i18n yet. The install
command, the wiring code, and the B2E vs B2C fallback configuration are all in the framework
reference (references/<framework>/localize.md and its i18n-setup.md).
Check:
Run check-i18n-wired.sh from the UI bundle dir (it scans src/ relative to the current directory) and report what it returns. The script owns the whole deterministic inspection: it looks for the framework's i18n wiring (React: an initI18n() init file called at boot; Angular: provideTranslateService/TranslateModule.forRoot registering a custom TranslateLoader, loaded at boot via TranslateService.use), and when that exists it also reports whether the label manifest is imported and actually reaches the label backend/loader. Do not re-derive any of this by reading files yourself.
cd <path-to-uiBundles/<name>/ dir> # scripts scan src/ relative to here
bash <SKILL_DIR>/references/<framework>/check-i18n-wired.shBranch on the exit code (the printed message names the specific file/symbol for your report, but the decision is the code):
0 → fully wired, the manifest reaches the label backend/loader; just add new keys.1 → no i18n wiring exists; scaffold the whole setup per the framework reference.2 → the wiring exists but is incomplete (React: init not called at boot; Angular: loader not registered, or registered but no boot-time TranslateService.use); do not re-scaffold or overwrite it. Add only the missing wiring the message names, then re-run.3 → wired at boot but the script could not confirm the manifest reaches the backend/loader. This last check is a textual heuristic: the manifest may be wired through a variable, spread, factory, or helper the script can't see, so treat exit 3 as "verify before editing," not "definitely broken." Open the file the message names and confirm before reconciling; never re-scaffold or duplicate wiring that already works.64 → usage error: the source dir doesn't exist (wrong cwd or bad argument). This is not a "no wiring" result; do not scaffold. Fix the path and re-run.B2C override — applies even at exit 0: the wiring check only proves i18n exists, not that it is correct for B2C. A seed with B2E wiring — dir = ctx.dir and a loader with no labelFallback — passes check-i18n-wired.sh at exit 0 but is wrong for a B2C site. If the site is B2C, don't stop at "add new keys": open src/i18n/index.ts (or the framework's init file) and, using resolvedLang (= SFDC_ENV.language || ctx.lang; the detector does not read SFDC_ENV.language), (a) add labelFallback: "USER_DEFAULT", (b) set direction from it — i18next.dir(resolvedLang), never ctx.dir, and (c) initialize in it — React lng: resolvedLang in i18next.init; Angular translate.use(resolvedLang). See references/<framework>/i18n-setup.md. Never leave B2E wiring on a B2C site.
Completion criterion:
The i18n wiring exists and is called once at boot; the manifest reaches the label backend/loader. For B2C, all three resolvedLang overrides are applied — USER_DEFAULT fallback, display language (React lng, Angular translate.use), and i18next.dir(resolvedLang) direction — not the seed's B2E defaults.
Follow the framework reference for the exact scaffold and never clobber existing wiring.
Pause: "i18n setup [exists / created]. It's loaded at boot: [confirm]."
Goal: Guide the developer to verify labels render in a second language.
Action: Follow the branch-specific procedure in references/common/verifying.md.
For B2E, activate a second language, author or retrieve its translation metadata, build against the target org, deploy only the target bundle and label metadata, then change the authenticated user's Language and reload.
For B2C, verify configured site languages, URL routing, SFDC_ENV.language, the full-reload language switcher, localized local preview, guest GraphQL access, and cache clearing as detailed in the framework reference.
Deploying the bundle, labels, and translations does not publish the Experience site. Treat sf community publish as a separate go-live mutation: show the exact site and target org, then wait for explicit user confirmation immediately before running it.
If it doesn't render: check the gotchas in references/common/gotchas.md:
i18next_res_* in localStorage; Angular: in-memory, reload refetches)GraphQLApiOrgPrefForGuestUsers is not admin-enabled)SFDC_ENV.language disagreeCompletion criterion: Labels render in ≥2 locales, or the blocking gotcha is identified.
Pause: "To verify: activate a second language in Translation Workbench, author a translation (I can scaffold the XML), build/deploy, and reload. Want me to scaffold the translation file for [language]? [y / I'll do it manually]"
<Translations> document with a closed <customLabels> block per label and XML-escaped English source text. Preserve placeholders and parse both metadata files before completion. Translators replace scaffold values by hand or through Translation Workbench; never call an MT API for them.initI18n(), reconcile (add the manifest import if missing) rather than replace the whole file.webapps, core-only paths, or internal infrastructure references anywhere. Write as if for an external customer in an SFDX project.sf community publish only after showing the site and org and receiving explicit confirmation for that publication.<project-root>/ ← SFDX project root
└── force-app/main/default/
├── labels/CustomLabels.labels-meta.xml ← English base labels
├── translations/<locale>.translation-meta.xml ← one per translated language
└── uiBundles/<your-bundle>/
├── package.json
└── src/
├── i18n/
│ ├── index.ts ← init wiring (you write this once)
│ └── label-manifest.ts ← list of labels to fetch (you maintain this)
└── components/ ← components call the translation function| Command | Run from | Purpose |
|---|---|---|
Install i18n dependencies (see references/<framework>/localize.md) | UI bundle dir | Install the framework's i18n libraries (Step 4) |
npm run build | UI bundle dir | Build the app (API version bakes in, set target-org first) |
See references/<framework>/verifying.md | Project root | Review and deploy the exact target bundle + changed label metadata to an explicit org |
sf project retrieve start --metadata Translations:<locale> | Project root | Pull translations authored in Translation Workbench |
CustomLabels entry and a translation calllabel-manifest.ts entry count == label count (no unregistered keys)USER_DEFAULT configured, and site language route matches SFDC_ENV.language*-meta.xml (only scaffold-and-guide)<Translations> root and one closed block per label© forcedotcom, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 18 other files (scripts, references) in skills/experience-ui-bundle-localize of forcedotcom/sf-skills.
Open the folder on GitHubat commit 3c15867
Experience UI Bundle Localize next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Experience UI Bundle Localize this skillforcedotcom/sf-skills | 1.1k | — | ~5.8k | Automated safety check: Pass | Apache-2.0 | |
| Cometchat I18ncometchat/cometchat-skills | 129 | — | ~1.9k | Automated safety check: Pass | MIT | |
| Lingui Best PracticesB0und/WikiSpeedrun | 133 | 2 repos | ~4.2k | Automated safety check: Pass | MIT | |
| I18next Localizationi18next/i18next-cli | 242 | — | ~1.6k | Automated safety check: Pass | MIT | |
| Add LanguageZoneMinder/zmNinjaNg | 110 | — | ~1.1k | Automated safety check: Pass | Apache-2.0 | |
| Translate CraftEliasOulkadi/shokunin | 114 | — | ~2.4k | Automated safety check: Pass | MIT |
cometchat/cometchat-skills
Localize a CometChat integration — set the UI Kit language, register custom/overridden translations, handle RTL, and never leak a raw localization key into the UI.
B0und/WikiSpeedrun
Implement internationalization with Lingui in React and JavaScript applications.
i18next/i18next-cli
Takes an app from hardcoded strings to a localized, continuously translated one with i18next (Locize optional): stack detection, config, wrapping strings in t(), key extraction, Locize sync, and AI…
ZoneMinder/zmNinjaNg
A skill your agent uses when adding a new interface language (locale) to the app, or when asked to translate the UI into another language.
EliasOulkadi/shokunin
Professional translation and localization for 8 languages (ES, JA, FR, DE, PT, ZH, KO, AR).
langflow-ai/langflow
Add, change, or review user-facing text in the Langflow frontend using the i18n system (i18next / react-i18next).
forcedotcom/sf-skills
Declared architecture snapshot for one Agentforce agent: planner, topics, actions, flows, Apex, prompt templates, and NGA plugins.
forcedotcom/sf-skills
Data Cloud 360° view of a single Agentforce session. An agent skill from forcedotcom/sf-skills.
forcedotcom/sf-skills
Apply a Salesforce sandbox post-copy automation JSON config against a target org.
forcedotcom/sf-skills
Apply a Salesforce sandbox post-copy automation JSON config against a target org.
forcedotcom/sf-skills
Apply SLDS-compliant UI using the correct blueprints, styling hooks, utility classes, and icons.
forcedotcom/sf-skills
Lightning Web Components with PICKLES methodology and 165-point scoring.
Works with
MUST activate to localize / internationalize a uiBundles//src/ project (React or Angular): extract hardcoded user-facing strings into Custom Labels, wire a runtime i18n library over the Platform SDK…. Experience UI Bundle Localize is an agent skill from forcedotcom/sf-skills. MUST activate to localize / internationalize a uiBundles//src/ project (React or Angular): extract hardcoded user-facing strings into Custom Labels, wire a runtime i18n library over the Platform SDK backend, add labels for another language, or troubleshoot label rendering across locales.
Experience UI Bundle Localize fits situations like: B2B site bundles; building app shell/UI; reading/writing/refreshing records (use experience-ui-bundle-salesforce-data-access); generating a new bundle (use experience-ui-bundle-frontend-generate).
Run `npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-localize -a claude-code`. Or copy the skill folder (skills/experience-ui-bundle-localize in forcedotcom/sf-skills) into .claude/skills/experience-ui-bundle-localize in your project. Claude Code loads it when a task matches its description.
Run `npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-localize -a codex`. Or copy the skill folder (skills/experience-ui-bundle-localize in forcedotcom/sf-skills) into .agents/skills/experience-ui-bundle-localize in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-localize -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/experience-ui-bundle-localize, .gemini/skills/experience-ui-bundle-localize, .github/skills/experience-ui-bundle-localize and .opencode/skills/experience-ui-bundle-localize in your project.
Going by SKILL.md and its folder, Experience UI Bundle Localize needs a shell for the scripts in its folder and the command-line tools its instructions call (bash, sf and npm). Our summary lists: A Bash shell.
SKILL.md contains no URLs. Its commands use npm, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Experience UI Bundle Localize is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.8k tokens (SKILL.md is roughly 23k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 30k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Experience UI Bundle Localize: Cometchat I18n (cometchat/cometchat-skills, 129 stars), Lingui Best Practices (B0und/WikiSpeedrun, 133 stars), I18next Localization (i18next/i18next-cli, 242 stars) and Add Language (ZoneMinder/zmNinjaNg, 110 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
forcedotcom (a GitHub organization) maintains it in forcedotcom/sf-skills, which has 1,058 GitHub stars. The repository holds 248 skills in this directory. The repository was last updated on October 3, 2026.
Source: forcedotcom/sf-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.