@salesforce/afv-skills 1.34.0 → 1.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/package.json +1 -1
  2. package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +239 -0
  3. package/skills/automation-sandbox-post-copy-config-generate/assets/config_template.json +21 -0
  4. package/skills/automation-sandbox-post-copy-config-generate/assets/json_schema.json +90 -0
  5. package/skills/automation-sandbox-post-copy-config-generate/examples/sample_sop_excerpt.md +31 -0
  6. package/skills/automation-sandbox-post-copy-config-generate/examples/sample_sop_to_config.json +50 -0
  7. package/skills/automation-sandbox-post-copy-config-generate/references/configuration_catalog.md +76 -0
  8. package/skills/automation-sandbox-post-copy-config-generate/references/sop_parsing_patterns.md +157 -0
  9. package/skills/automation-sandbox-post-copy-config-generate/references/source_format_handling.md +230 -0
  10. package/skills/dx-apexguru-scan/SKILL.md +403 -0
  11. package/skills/dx-apexguru-scan/examples/README.md +54 -0
  12. package/skills/dx-apexguru-scan/examples/sample-decoded-summary.json +176 -0
  13. package/skills/dx-apexguru-scan/examples/sample-full-no-runtime-response.json +26 -0
  14. package/skills/dx-apexguru-scan/examples/sample-succeeded-response.json +15 -0
  15. package/skills/dx-apexguru-scan/references/api-reference.md +81 -0
  16. package/skills/dx-apexguru-scan/references/authentication.md +134 -0
  17. package/skills/dx-apexguru-scan/references/error-handling.md +56 -0
  18. package/skills/dx-apexguru-scan/references/violation-catalog.md +28 -0
  19. package/skills/dx-apexguru-scan/scripts/build-zip.sh +87 -0
  20. package/skills/dx-apexguru-scan/scripts/decode-report.js +389 -0
  21. package/skills/dx-apexguru-scan/scripts/resolve-token.sh +151 -0
  22. package/skills/dx-apexguru-scan/scripts/run-scan.sh +153 -0
  23. package/skills/dx-apexguru-scan/scripts/scan.sh +96 -0
  24. package/skills/dx-apexguru-scan/scripts/validate-token.js +121 -0
  25. package/skills/dx-app-analytics-query/SKILL.md +2 -0
  26. package/skills/dx-devops-pipeline-manage/SKILL.md +263 -0
  27. package/skills/dx-devops-pipeline-manage/examples/common-workflows.md +177 -0
  28. package/skills/dx-devops-pipeline-manage/references/cli-commands.md +298 -0
  29. package/skills/dx-devops-pipeline-manage/references/parsing-patterns.md +134 -0
  30. package/skills/dx-devops-pipeline-manage/scripts/check-activation-ready.sh +34 -0
  31. package/skills/dx-devops-pipeline-manage/scripts/validate-org-type.sh +17 -0
  32. package/skills/dx-devops-pipeline-manage/scripts/verify-operation.sh +82 -0
  33. package/skills/dx-devops-promote/SKILL.md +214 -0
  34. package/skills/dx-devops-promote/examples/promotion-workflows.md +212 -0
  35. package/skills/dx-devops-promote/references/cli-commands.md +303 -0
  36. package/skills/experience-lwc-base-components-integrate/SKILL.md +176 -0
  37. package/skills/experience-lwc-base-components-integrate/references/lbc-expert-guidance.md +127 -0
  38. package/skills/experience-lwc-base-components-integrate/references/lightning-component-index.md +179 -0
  39. package/skills/experience-lwc-base-components-integrate/references/lightning-components.md +5429 -0
  40. package/skills/experience-lwc-base-components-integrate/scripts/extract-component-docs.sh +61 -0
  41. package/skills/experience-lwc-rtl-validate/SKILL.md +149 -0
  42. package/skills/experience-lwc-rtl-validate/references/rtl-expert.md +892 -0
  43. package/skills/experience-lwc-rtl-validate/scripts/scan-rtl-css.sh +206 -0
  44. package/skills/experience-lwc-typescript-migrate/SKILL.md +207 -0
  45. package/skills/experience-lwc-typescript-migrate/assets/dts-template.ts +15 -0
  46. package/skills/experience-lwc-typescript-migrate/assets/type-patterns.ts +44 -0
  47. package/skills/experience-lwc-typescript-migrate/scripts/find-consumers.sh +128 -0
  48. package/skills/experience-ui-bundle-localize/SKILL.md +323 -0
  49. package/skills/experience-ui-bundle-localize/references/gotchas.md +249 -0
  50. package/skills/experience-ui-bundle-localize/references/i18n-setup.md +169 -0
  51. package/skills/experience-ui-bundle-localize/references/interpolation.md +311 -0
  52. package/skills/experience-ui-bundle-localize/references/label-xml.md +282 -0
  53. package/skills/experience-ui-bundle-localize/references/verifying.md +219 -0
  54. package/skills/experience-ui-bundle-localize/scripts/check-i18n-wired.sh +195 -0
  55. package/skills/experience-ui-bundle-localize/scripts/check-manifest-registered.sh +100 -0
  56. package/skills/experience-ui-bundle-localize/scripts/check-org-api-version.sh +40 -0
  57. package/skills/experience-ui-bundle-localize/scripts/detect-bundle-type.sh +57 -0
  58. package/skills/experience-ui-bundle-site-generate/SKILL.md +3 -0
  59. package/skills/mobile-apps-create/SKILL.md +1 -3
  60. package/skills/platform-custom-lightning-type-generate/SKILL.md +3 -0
  61. package/skills/platform-custom-lightning-type-generate/assets/primitive-types-and-constraints.md +1 -1
  62. package/skills/platform-mcp-tool-widget-coordinate/SKILL.md +250 -0
  63. package/skills/platform-mcp-tool-widget-coordinate/examples/action-name-source-prompt.md +74 -0
  64. package/skills/platform-mcp-tool-widget-coordinate/examples/apex-invocable-source-prompt.md +90 -0
  65. package/skills/platform-mcp-tool-widget-coordinate/examples/nested-object-source-prompt.md +191 -0
  66. package/skills/platform-mcp-tool-widget-coordinate/examples/pasted-tool-output-prompt.md +85 -0
  67. package/skills/platform-mcp-tool-widget-coordinate/references/build-plan-format.md +74 -0
  68. package/skills/platform-mcp-tool-widget-coordinate/references/mcp-tool-output-discovery.md +184 -0
  69. package/skills/platform-mcp-tool-widget-coordinate/references/two-clt-modeling.md +128 -0
  70. package/skills/platform-mcp-tool-widget-coordinate/references/validation-gates.md +181 -0
@@ -0,0 +1,282 @@
1
+ # Label XML: Custom Labels and translation metadata shapes
2
+
3
+ This covers the two metadata XML files you author: the English base labels and the per-language translations.
4
+
5
+ ---
6
+
7
+ ## Custom Labels: `force-app/main/default/labels/CustomLabels.labels-meta.xml`
8
+
9
+ This holds the **English base labels**: the source of truth for label content.
10
+
11
+ ### Structure
12
+
13
+ ```xml
14
+ <?xml version="1.0" encoding="UTF-8"?>
15
+ <CustomLabels xmlns="http://soap.sforce.com/2006/04/metadata">
16
+ <labels>
17
+ <fullName>Welcome_Text</fullName>
18
+ <language>en_US</language>
19
+ <protected>false</protected>
20
+ <shortDescription>Welcome banner heading</shortDescription>
21
+ <value>Welcome</value>
22
+ </labels>
23
+ <labels>
24
+ <fullName>Save_Button</fullName>
25
+ <language>en_US</language>
26
+ <protected>false</protected>
27
+ <shortDescription>Save button label</shortDescription>
28
+ <value>Save</value>
29
+ </labels>
30
+ </CustomLabels>
31
+ ```
32
+
33
+ ### Fields
34
+
35
+ | Field | Purpose | Notes |
36
+ |---|---|---|
37
+ | `<fullName>` | The label's API name | Used in `t("Key")` calls and the manifest (`"c:Welcome_Text"`). PascalCase, descriptive, unique. |
38
+ | `<language>` | Language code | Always `en_US` for the base label file. |
39
+ | `<protected>` | Managed package protection | Always `false` for custom labels in your org (you can edit them). |
40
+ | `<shortDescription>` | Internal description | For translators/developers, not shown to users. Describe what the label is for. |
41
+ | `<value>` | The English text | What the user sees. Can include `{0}`, `{1}` placeholders for interpolation. |
42
+
43
+ ### Key naming conventions
44
+
45
+ Choose keys that are:
46
+ - **Descriptive**: `Welcome_Text` is better than `Label1`
47
+ - **Context-aware**: `Save_Button` vs `Save_Failed_Message` (same verb, different role)
48
+ - **Unique**: two labels shouldn't share a key even if the current text happens to match
49
+
50
+ Format: `<Context>_<Role>` in PascalCase with underscores between parts.
51
+
52
+ **Examples:**
53
+ - `"Welcome"` → `Welcome_Text` or `Welcome_Heading`
54
+ - `"Save"` → `Save_Button`
55
+ - `"Failed to save {0}: {1}"` → `Save_Failed_Message`
56
+ - `"Showing {0} of {1} records"` → `Record_Count_Display`
57
+
58
+ ---
59
+
60
+ ## Translations: `force-app/main/default/translations/<locale>.translation-meta.xml`
61
+
62
+ One file per translated language (e.g., `es.translation-meta.xml` for Spanish, `fr.translation-meta.xml` for French, `ja.translation-meta.xml` for Japanese).
63
+
64
+ ### Structure
65
+
66
+ ```xml
67
+ <?xml version="1.0" encoding="UTF-8"?>
68
+ <Translations xmlns="http://soap.sforce.com/2006/04/metadata">
69
+ <customLabels>
70
+ <label>Bienvenido</label>
71
+ <name>Welcome_Text</name>
72
+ </customLabels>
73
+ <customLabels>
74
+ <label>Guardar</label>
75
+ <name>Save_Button</name>
76
+ </customLabels>
77
+ </Translations>
78
+ ```
79
+
80
+ ### Fields
81
+
82
+ | Field | Purpose | Notes |
83
+ |---|---|---|
84
+ | `<name>` | The label's API name | Must exactly match the `<fullName>` in `CustomLabels.labels-meta.xml`. |
85
+ | `<label>` | The translated text | What the user sees in this language. Preserve `{0}`, `{1}` placeholders. |
86
+
87
+ ### File naming
88
+
89
+ The filename is `<locale>.translation-meta.xml`, where `<locale>` is the Salesforce Language code:
90
+ - `es.translation-meta.xml`: Spanish
91
+ - `fr.translation-meta.xml`: French
92
+ - `de.translation-meta.xml`: German
93
+ - `ja.translation-meta.xml`: Japanese
94
+ - `pt_BR.translation-meta.xml`: Portuguese (Brazil)
95
+ - `zh_CN.translation-meta.xml`: Chinese (Simplified)
96
+ - `zh_TW.translation-meta.xml`: Chinese (Traditional)
97
+
98
+ See Salesforce's [Supported Languages](https://help.salesforce.com/s/articleView?id=sf.faq_getstart_what_languages_does.htm) for the full list.
99
+
100
+ ---
101
+
102
+ ## How translations are authored
103
+
104
+ You have two options:
105
+
106
+ ### 1. Hand-edit the XML (for small apps)
107
+
108
+ Create the `<locale>.translation-meta.xml` file, add one `<customLabels>` block per label, and type the translations directly. Good for a handful of labels or prototyping.
109
+
110
+ ### 2. Use Translation Workbench (for scale)
111
+
112
+ Salesforce's **Translation Workbench** is the in-org UI where translators enter translations, which you then pull down as deployable `.translation-meta.xml` files.
113
+
114
+ **Workflow:**
115
+ 1. **Enable Translation Workbench**, Setup → Translation Workbench → Translation Settings → Enable
116
+ 2. **Add languages**, same Settings page → Add the languages you plan to support
117
+ 3. **Enter translations**, Setup → Translation Workbench → Translate → pick:
118
+ - **Setup Component:** Custom Label
119
+ - **Language:** the target language
120
+ - **Label:** the label to translate
121
+ - Type the translation, Save
122
+ 4. **Retrieve as metadata**, pull the translations into your project:
123
+ ```bash
124
+ sf project retrieve start --metadata Translations:es
125
+ sf project retrieve start --metadata Translations:fr
126
+ # etc., one per language
127
+ ```
128
+ The CLI writes the `.translation-meta.xml` files to `force-app/main/default/translations/`.
129
+
130
+ Reference: [Translation Workbench overview](https://help.salesforce.com/s/articleView?id=sf.customize_wbench.htm)
131
+
132
+ ---
133
+
134
+ ## Namespace:Key format
135
+
136
+ In the **manifest** (`src/i18n/label-manifest.ts`) and some SDK contexts, labels are written as `"namespace:Key"`:
137
+
138
+ ```typescript
139
+ export const labelManifest = [
140
+ "c:Welcome_Text",
141
+ "c:Save_Button",
142
+ ];
143
+ ```
144
+
145
+ - `c` = the custom label namespace (your org's labels)
146
+ - `Welcome_Text` = the `<fullName>` from `CustomLabels.labels-meta.xml`
147
+
148
+ Other namespaces exist (e.g., `LightningDatatable` for framework-shipped labels), but most bundles only use `c`.
149
+
150
+ In component code, the namespace is usually implicit (set via `defaultNS: "c"` in the init), so you call `t("Welcome_Text")` not `t("c:Welcome_Text")`.
151
+
152
+ ---
153
+
154
+ ## Interpolation: `{0}`, `{1}` placeholders
155
+
156
+ Labels can include **positional placeholders** for runtime substitution:
157
+
158
+ ```xml
159
+ <labels>
160
+ <fullName>Save_Failed_Message</fullName>
161
+ <language>en_US</language>
162
+ <protected>false</protected>
163
+ <shortDescription>Error message when save fails</shortDescription>
164
+ <value>Failed to save {0}: {1}</value>
165
+ </labels>
166
+ ```
167
+
168
+ At call time:
169
+
170
+ ```typescript
171
+ t("Save_Failed_Message", { 0: "Account", 1: "Permission denied" });
172
+ // → "Failed to save Account: Permission denied"
173
+ ```
174
+
175
+ **Translations must preserve the placeholders:**
176
+
177
+ ```xml
178
+ <!-- es.translation-meta.xml -->
179
+ <customLabels>
180
+ <label>Error al guardar {0}: {1}</label>
181
+ <name>Save_Failed_Message</name>
182
+ </customLabels>
183
+ ```
184
+
185
+ The placeholders can move (Spanish grammar might flip the order), but they must stay as `{0}`, `{1}`; i18next does the substitution at render time.
186
+
187
+ See [interpolation.md](interpolation.md) for how this works under the hood.
188
+
189
+ ---
190
+
191
+ ## Deploy activation requirement
192
+
193
+ Before you can deploy a `<locale>.translation-meta.xml` file, the language must be **activated** in the org:
194
+
195
+ **Setup → Translation Workbench → Translation Settings → Add**
196
+
197
+ If you deploy a translation file for an inactive language, the deploy is rejected:
198
+ ```text
199
+ Not available for deploy for this organization
200
+ ```
201
+
202
+ English (`en_US`) needs no activation; it's always available.
203
+
204
+ ---
205
+
206
+ ## Language vs Locale (a common confusion)
207
+
208
+ Salesforce has two separate settings:
209
+ - **Language** drives **translations**: the text the user sees (`en_US`, `en_GB`, `de`, `pt_BR`)
210
+ - **Locale** drives **formatting only**: dates, numbers, currency (`de_DE`, `fr_CA`)
211
+
212
+ A user can have Language = English, Locale = French: English text, French number formatting.
213
+
214
+ When you "add a language" for localization, you're working in the **Language** dimension. The SDK's i18n context exposes both: `lang` (Language) picks the translation, and `locale`/`currency` (Locale) feed `Intl` formatters.
215
+
216
+ To change a user's Language (to test translations), go to:
217
+ **Setup → My Settings → Language & Time Zone → Language** → pick the language → Save.
218
+
219
+ ---
220
+
221
+ ## Example: full cycle for one label in two languages
222
+
223
+ ### 1. Add the English base label
224
+
225
+ `force-app/main/default/labels/CustomLabels.labels-meta.xml`:
226
+ ```xml
227
+ <labels>
228
+ <fullName>Welcome_Text</fullName>
229
+ <language>en_US</language>
230
+ <protected>false</protected>
231
+ <shortDescription>Welcome banner heading</shortDescription>
232
+ <value>Welcome</value>
233
+ </labels>
234
+ ```
235
+
236
+ ### 2. Add the Spanish translation
237
+
238
+ `force-app/main/default/translations/es.translation-meta.xml`:
239
+ ```xml
240
+ <customLabels>
241
+ <label>Bienvenido</label>
242
+ <name>Welcome_Text</name>
243
+ </customLabels>
244
+ ```
245
+
246
+ ### 3. Register in the manifest
247
+
248
+ `src/i18n/label-manifest.ts`:
249
+ ```typescript
250
+ export const labelManifest = ["c:Welcome_Text"];
251
+ ```
252
+
253
+ ### 4. Use in a component
254
+
255
+ ```typescript
256
+ import { useTranslation } from "react-i18next";
257
+
258
+ function WelcomeBanner() {
259
+ const { t } = useTranslation("c");
260
+ return <h1>{t("Welcome_Text")}</h1>;
261
+ }
262
+ ```
263
+
264
+ ### 5. Deploy
265
+
266
+ ```bash
267
+ sf project deploy start --source-dir force-app --target-org <alias>
268
+ ```
269
+
270
+ ### 6. Verify
271
+
272
+ - User with Language = English sees "Welcome"
273
+ - User with Language = Spanish sees "Bienvenido"
274
+
275
+ ---
276
+
277
+ ## Related
278
+
279
+ - [i18n-setup.md](i18n-setup.md): the init file + manifest wiring
280
+ - [interpolation.md](interpolation.md): how `{0}/{1}` substitution works
281
+ - [verifying.md](verifying.md): the serve/verify flow
282
+ - [gotchas.md](gotchas.md): silent-fail traps
@@ -0,0 +1,219 @@
1
+ # Verifying: serve, deploy, and test labels across locales
2
+
3
+ How to build, deploy, open, and verify that labels render correctly in multiple languages.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ Verification has five steps:
10
+ 1. **Build** the app (API version bakes in, point at the deploy target org first)
11
+ 2. **Deploy** the bundle + labels + translations in one shot
12
+ 3. **Open** the app at the correct URL (on the `lightning.force.com` domain)
13
+ 4. **Flip** the user's Language setting to the translated language
14
+ 5. **Reload** and confirm the labels render in the new language
15
+
16
+ ---
17
+
18
+ ## Step 1: Build the app
19
+
20
+ **Before building**, set the target org so the API version matches:
21
+
22
+ ```bash
23
+ sf config set target-org=<your-org-alias>
24
+ ```
25
+
26
+ **Why this matters:** The build plugin reads your **default org's** API version and stamps it into the bundle's JavaScript (`services/data/v{N}/graphql`). If you build while pointed at a v65.0 org and deploy to a v63.0 org, the bundle calls a GraphQL endpoint that org doesn't have, the call **404s, the i18n context fetch throws, and the app boots to a blank page** with no obvious error.
27
+
28
+ Then build:
29
+
30
+ ```bash
31
+ npm run build
32
+ ```
33
+
34
+ (Run from the UI bundle directory, `force-app/main/default/uiBundles/<your-bundle>/`.)
35
+
36
+ The built output lands in `dist/` under the bundle directory. The deploy pushes the built JS, not your TypeScript source.
37
+
38
+ ---
39
+
40
+ ## Step 2: Activate languages in the org (before deploy)
41
+
42
+ For every non-English language you're deploying, **activate it first** in the org:
43
+
44
+ **Setup → Translation Workbench → Translation Settings → Add**
45
+
46
+ Pick the languages (e.g., Spanish, French, German) and Save.
47
+
48
+ **Why:** Deploying a `<locale>.translation-meta.xml` for an inactive language fails with:
49
+ ```text
50
+ Not available for deploy for this organization
51
+ ```
52
+
53
+ English (`en_US`) needs no activation; it's always available.
54
+
55
+ ---
56
+
57
+ ## Step 3: Deploy the bundle + labels + translations
58
+
59
+ Deploy the entire `force-app` tree (bundle, labels, translations) in one command:
60
+
61
+ ```bash
62
+ sf project deploy start --source-dir force-app --target-org <your-org-alias>
63
+ ```
64
+
65
+ **Run from the SFDX project root** (not from inside the bundle directory). `--source-dir force-app` deploys everything under that folder:
66
+ - `labels/CustomLabels.labels-meta.xml` (English base labels)
67
+ - `translations/<locale>.translation-meta.xml` (translated labels)
68
+ - `uiBundles/<your-bundle>/dist/` (the built app)
69
+
70
+ You do **not** need a `package.xml` or any manifest entry; the CLI discovers the metadata automatically.
71
+
72
+ **Point at `force-app`, not `uiBundles/`, or your labels and translations won't go up.**
73
+
74
+ ---
75
+
76
+ ## Step 4: Open the app
77
+
78
+ UI Bundles serve at a fixed LWR route:
79
+
80
+ ```text
81
+ https://<your-org>.lightning.force.com/lwr/application/ai/<namespace>-<bundleName>
82
+ ```
83
+
84
+ **Parts:**
85
+ - `<your-org>`: your org's My Domain (e.g., `mycompany-dev-ed`)
86
+ - `<namespace>`: the bundle's namespace (usually `c` for custom)
87
+ - `<bundleName>`: the bundle's name (lowercased; the framework lowercases `appName` at lookup, so camelCase silently 404s)
88
+
89
+ **Example:** `https://mycompany-dev-ed.lightning.force.com/lwr/application/ai/c-freshi18n`
90
+
91
+ The `/lwr/application/ai/` segment is a fixed LWR route prefix; it's the same for every UI Bundle and isn't something you configure.
92
+
93
+ **Enhanced-domain orgs (scratch orgs are enhanced by default) redirect:** Type the `lightning.force.com` URL above, and the browser **redirects** to the standalone-app host:
94
+
95
+ ```text
96
+ https://<your-org>--<namespace>.<instance>.my.salesforce.app/lwr/application/ai/<namespace>-<bundleName>
97
+ ```
98
+
99
+ That's expected: a UI Bundle is a standalone **LWR** app, not part of Lightning Experience, so it serves from the `.my.salesforce.app` app host. The `lightning.force.com` URL is fine to type (it forwards); just don't be surprised when the address bar ends on `.my.salesforce.app`.
100
+
101
+ **If you see a blank page:**
102
+ - You're probably on the raw `my.salesforce.com` (API/session) host; switch to `lightning.force.com` and let it redirect.
103
+ - Or the API version is baked in wrong (built against a different org), see Step 1.
104
+ - Or the bundle name is camelCased in the URL (the framework lowercases it; use all lowercase).
105
+
106
+ See [gotchas.md](gotchas.md) for the full list of blank-page causes.
107
+
108
+ ---
109
+
110
+ ## Step 5: Change the user's Language
111
+
112
+ To test translations, you need to change the **Language** setting (not Locale, see the note below).
113
+
114
+ **Setup → My Settings → Language & Time Zone → Language** → pick the language you translated (e.g., Spanish) → Save.
115
+
116
+ **Reload the app.** Labels should now render in the selected language.
117
+
118
+ ---
119
+
120
+ ## Language vs Locale (common confusion)
121
+
122
+ Salesforce has two separate settings:
123
+ - **Language** drives **translations**: the text the user sees (`en_US`, `es`, `de`, `fr`)
124
+ - **Locale** drives **formatting only**: dates, numbers, currency (`en_US`, `de_DE`, `fr_CA`)
125
+
126
+ A user can have Language = English, Locale = French: English text, French number formatting.
127
+
128
+ When you test localization, **change the Language**, not the Locale. Changing Locale won't flip label text.
129
+
130
+ ---
131
+
132
+ ## Troubleshooting: labels don't flip
133
+
134
+ ### 1. Label shows in English when it should be translated
135
+
136
+ **Possible causes:**
137
+ - The language isn't activated (Step 2), though you'd have hit the deploy rejection if that were it.
138
+ - The translation file is missing that label, or its `<name>` doesn't match the `<fullName>` in `CustomLabels`.
139
+ - The user's **Language** isn't what you think; confirm it's set to the language you translated (not Locale).
140
+
141
+ **Check:** Go to Setup → Translation Workbench → Translate → pick the language and the label. Is the translation there? If not, author it and re-deploy.
142
+
143
+ **Fallback behavior:** If a key is in the manifest but untranslated for the active language, i18next renders the **English base value** (via `fallbackLng: "en"` in the init). That's correct behavior; it just means that one key wasn't translated yet.
144
+
145
+ ---
146
+
147
+ ### 2. Label shows as its own key name
148
+
149
+ You see the literal string `Welcome_Text` on screen instead of "Welcome."
150
+
151
+ **Cause:** The key isn't in your `label-manifest.ts`. The app only fetches labels listed in the manifest, so an unregistered key is **never requested**, and i18next, finding nothing, renders the key string. **No console warning, no error**; it fails silently.
152
+
153
+ **Fix:** Add the `"c:Key"` entry to `label-manifest.ts` (Step 3 of the workflow). This is the most common localization bug; if a label looks wrong, check the manifest first.
154
+
155
+ See [gotchas.md](gotchas.md) for the full explanation.
156
+
157
+ ---
158
+
159
+ ### 3. You changed a translation but the app still shows the old text
160
+
161
+ You edited a label in the Translation Workbench (or redeployed a `translation-meta.xml`), confirmed the new value is in the org, but the app keeps rendering the **previous** value on reload.
162
+
163
+ **Cause:** The label cache. Your `src/i18n/index.ts` chains two backends, `[LocalStorageBackend, SalesforceBackend]`, so on load i18next reads labels from **localStorage first** and only falls through to GraphQL on a cache miss. Labels are cached per language+namespace under keys like `i18next_res_de-c` (DevTools → Application → Local Storage), with a 24-hour `expirationTime`. Until that entry expires, your app serves the cached copy and never refetches.
164
+
165
+ **Fix:** Clear the cached labels, then reload:
166
+ - **DevTools → Application → Local Storage** → delete the `i18next_res_*` keys
167
+ - Or **Clear site data** to wipe everything
168
+
169
+ The next load misses the cache, refetches over GraphQL, and shows the current value.
170
+
171
+ **This is expected behavior, not a bug.** The cache is what makes labels fast after first load. In production, a translation change takes up to `expirationTime` (24 hours) to roll out; during development, clear the cache to see edits immediately.
172
+
173
+ See [gotchas.md](gotchas.md) for the full explanation.
174
+
175
+ ---
176
+
177
+ ### 4. A user on a regional Language (e.g., `en_GB`) sees English base text, not their locale's translation
178
+
179
+ This is expected, not a bug, **as long as you only authored the base (`en_US`) translation.**
180
+
181
+ Asked with `fallback: BASE_VALUE`, the GraphQL server returns the label's base value for a regional Language it has no explicit translation for: `resolvedLocale` comes back as the base (`en_US`) with `wasFallback: true`. The server does **not** map `en_GB → en_US` region-aware; it just honors the base-value fallback. On the documented SDK floor (11.42.1) the backend does not yet request `BASE_VALUE`, so it resolves with the server default (`USER_DEFAULT`): a guest or org-default user still lands on the base value, but see the related note below for the logged-in case. The base-value request ships in a later SDK release (see [gotchas.md](gotchas.md)).
182
+
183
+ **Fix (only if you want region-specific text):** Author a translation for that exact regional Language (`en_GB.translation-meta.xml`). Otherwise the base value is the intended, correct result.
184
+
185
+ **Related:** if instead a *logged-in* user sees **their own** language (not the org default) for an untranslated label, that's the fallback-strategy case, see [gotchas.md](gotchas.md) ("Logged-in user sees their own language instead of the org default"). On 11.42.1 that is the expected behavior, since the backend still uses `USER_DEFAULT`; author an explicit org-default translation to avoid it. The `BASE_VALUE` fallback that prevents it arrives in a later SDK release.
186
+
187
+ ---
188
+
189
+ ## Verification checklist
190
+
191
+ Use this to confirm everything works:
192
+
193
+ - [ ] Built against the correct org (API version matches deploy target)
194
+ - [ ] Every translated language is activated in the org
195
+ - [ ] Deployed `force-app` (bundle + labels + translations in one shot)
196
+ - [ ] Opened at `lightning.force.com/lwr/application/ai/<namespace>-<bundleName>` (redirected to `.my.salesforce.app` is fine)
197
+ - [ ] Changed user's **Language** (not Locale) to the translated language
198
+ - [ ] Reloaded, labels render in the new language
199
+ - [ ] If labels are stale, cleared `i18next_res_*` from localStorage
200
+
201
+ ---
202
+
203
+ ## Quick reference: commands
204
+
205
+ | Command | Run from | Purpose |
206
+ |---|---|---|
207
+ | `sf config set target-org=<alias>` | Anywhere | Set default org (API version bakes in on next build) |
208
+ | `npm run build` | UI bundle dir | Build the app |
209
+ | `sf project deploy start --source-dir force-app --target-org <alias>` | Project root | Deploy bundle + labels + translations |
210
+ | `sf project retrieve start --metadata Translations:<locale>` | Project root | Pull translations authored in Translation Workbench |
211
+
212
+ ---
213
+
214
+ ## Related
215
+
216
+ - [i18n-setup.md](i18n-setup.md): the init file + manifest
217
+ - [label-xml.md](label-xml.md): Custom Labels + translations metadata
218
+ - [interpolation.md](interpolation.md): `{0}/{1}` placeholders
219
+ - [gotchas.md](gotchas.md): silent-fail traps (unregistered keys, stale cache, API-version mismatch)