feat: allow customization of HTML lang attribute #41593
Conversation
…d browser translations Add per-app htmlLang setting in App Settings > General that sets the <html lang=""> attribute on published apps via react-helmet. Includes instance-level APPSMITH_DEFAULT_HTML_LANG env var with graceful fallback to "en" when unset. Adds notranslate directives and translate="no" to the app shell, editor UI containers, and widget iframe templates to prevent browsers and extensions from auto-translating content. Closes: appsmithorg/appsmith-ee#6642 Made-with: Cursor
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds HTML language propagation and translation suppression across public pages, runtime config, settings UI, viewer rendering, and server application detail data. ChangesHTML language propagation and translation suppression
Estimated code review effort: 4 (Complex) | ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (3 warnings)
✅ Passed checks (2 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (1)
498-517: Consider adding basic BCP 47 validation.The input accepts any free-form text, but the PR objective states it "accepts BCP 47 language codes." Invalid codes won't break functionality but won't help accessibility either. A simple regex check (e.g.,
/^[a-zA-Z]{2,3}(-[a-zA-Z0-9]+)*$/) with an error message would improve UX.💡 Optional: Add basic validation
+ const BCP47_REGEX = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]+)*$/; + const [isHtmlLangValid, setIsHtmlLangValid] = useState(true); + const validateHtmlLang = (value: string) => { + if (!value.trim()) return true; // Empty is valid (falls back to default) + return BCP47_REGEX.test(value.trim()); + }; <Input id="t--general-settings-app-language" + isValid={isHtmlLangValid} + errorMessage={isHtmlLangValid ? undefined : "Invalid language code (e.g., en, de, fr-CA)"} label={createMessage(GENERAL_SETTINGS_APP_LANGUAGE_LABEL)} - onBlur={() => saveHtmlLang(htmlLang)} - onChange={(value: string) => setHtmlLang(value)} + onBlur={() => { + if (validateHtmlLang(htmlLang)) saveHtmlLang(htmlLang); + }} + onChange={(value: string) => { + setHtmlLang(value); + setIsHtmlLangValid(validateHtmlLang(value)); + }}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx` around lines 498 - 517, The language input currently accepts any text; add basic BCP 47 validation in the GeneralSettings component by validating htmlLang against a regex (e.g., /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]+)*$/) inside the onChange/onBlur/onKeyPress handlers for the Input used for htmlLang, set a local validation error state (e.g., htmlLangError) and display a small error Text beneath the Input using createMessage(GENERAL_SETTINGS_APP_LANGUAGE_TOOLTIP) style; prevent calling saveHtmlLang(htmlLang) when the value is invalid and ensure the Input shows the error state so users get immediate feedback.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/client/public/index.html`:
- Around line 2-5: The root <html> element currently hardcodes lang="en" which
delays language configuration until client-side boot; update the server-rendered
template so the root <html> element uses the APPSMITH_DEFAULT_HTML_LANG
environment value with a server-side fallback to "en" (the same source used
later in the client script), ensuring the initial HTML response advertises the
configured language; make the change where the root <html> tag is defined in
index.html and keep the existing client-side assignment (lines ~271-272) as-is
to remain consistent.
---
Nitpick comments:
In
`@app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx`:
- Around line 498-517: The language input currently accepts any text; add basic
BCP 47 validation in the GeneralSettings component by validating htmlLang
against a regex (e.g., /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]+)*$/) inside the
onChange/onBlur/onKeyPress handlers for the Input used for htmlLang, set a local
validation error state (e.g., htmlLangError) and display a small error Text
beneath the Input using createMessage(GENERAL_SETTINGS_APP_LANGUAGE_TOOLTIP)
style; prevent calling saveHtmlLang(htmlLang) when the value is invalid and
ensure the Input shows the error state so users get immediate feedback.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 632ba231-4d4c-4bee-abb4-ea8c444d719a
📒 Files selected for processing (18)
app/client/public/404.htmlapp/client/public/index.htmlapp/client/src/ce/api/ApplicationApi.tsxapp/client/src/ce/configs/index.tsapp/client/src/ce/configs/types.tsapp/client/src/ce/constants/messages.tsapp/client/src/entities/Application/types.tsapp/client/src/pages/AppIDE/components/AppSettings/AppSettings.tsxapp/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsxapp/client/src/pages/AppViewer/AppViewerHtmlTitle.tsxapp/client/src/pages/AppViewer/index.tsxapp/client/src/pages/Editor/PropertyPane/PropertyPaneTab.tsxapp/client/src/widgets/CustomWidget/component/index.tsxapp/client/src/widgets/ExternalWidget/component/index.tsxapp/client/src/widgets/wds/WDSCustomWidget/component/createHtmlTemplate.tsapp/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationDetailCE.javadeploy/docker/fs/opt/appsmith/caddy-reconfigure.mjsdeploy/docker/fs/opt/appsmith/templates/loading.html
Replace the hardcoded lang="en" with the Caddy template expression so the initial HTML response advertises the configured language before client-side React boots. Made-with: Cursor
There was a problem hiding this comment.
♻️ Duplicate comments (1)
app/client/public/index.html (1)
2-2:⚠️ Potential issue | 🟠 MajorKeep the
"en"fallback at the render site.Line 2 and Lines 271-272 still collapse to an empty value when
APPSMITH_DEFAULT_HTML_LANGis unset, so the first HTML response can shiplang=""and the client config can exposedefaultHtmlLang: "". That makes the documented"en"default depend entirely on deploy-time env injection rather than the code path that renders it.What is the correct Caddy/templates syntax to render `{{env "APPSMITH_DEFAULT_HTML_LANG"}}` with a fallback of `"en"` when the environment variable is unset?Also applies to: 271-272
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/client/public/index.html` at line 2, Replace the bare template calls to {{env "APPSMITH_DEFAULT_HTML_LANG"}} in index.html with the Caddy template form that provides a fallback value, i.e. use the env function with a default: {{env "APPSMITH_DEFAULT_HTML_LANG" "en"}}; update the lang attribute at the top (the html tag) and the client-config insertion that sets defaultHtmlLang (the occurrences around lines 271-272) so they render "en" when APPSMITH_DEFAULT_HTML_LANG is unset.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@app/client/public/index.html`:
- Line 2: Replace the bare template calls to {{env
"APPSMITH_DEFAULT_HTML_LANG"}} in index.html with the Caddy template form that
provides a fallback value, i.e. use the env function with a default: {{env
"APPSMITH_DEFAULT_HTML_LANG" "en"}}; update the lang attribute at the top (the
html tag) and the client-config insertion that sets defaultHtmlLang (the
occurrences around lines 271-272) so they render "en" when
APPSMITH_DEFAULT_HTML_LANG is unset.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b39b056d-264f-46a9-94c3-d6743d19ddef
📒 Files selected for processing (1)
app/client/public/index.html
|
/build-deploy-preview skip-tests=true |
|
Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/22827220661. |
|
Deploy-Preview-URL: https://ce-41593.dp.appsmith.com |
There was a problem hiding this comment.
Review comments from Claude.
app/client/public/index.html — fallback gap in the <html lang> attribute
The <html> tag on line 2 uses:
<html lang='{{env "APPSMITH_DEFAULT_HTML_LANG"}}' translate="no">The template substitution in caddy-reconfigure.mjs replaces {{env "APPSMITH_DEFAULT_HTML_LANG"}} via:
(_, name) => (process.env[name] || extraEnv[name] || "")Since extraEnv.APPSMITH_DEFAULT_HTML_LANG is set to process.env.APPSMITH_DEFAULT_HTML_LANG || "en", the extraEnv fallback should kick in when the env var isn't set — so in a Docker-based deployment, the rendered HTML will correctly get lang="en". That part is fine.
However, in non-Docker environments (e.g. running the client dev server directly, or cloud deployments where caddy-reconfigure isn't the one serving index.html), the Caddy template expression may not be processed at all, which would leave lang='' verbatim in the HTML, or the browser receiving the unprocessed template string. It would be safer to set an explicit fallback at the template level itself. If Caddy's template syntax supports a default, something like:
{{env "APPSMITH_DEFAULT_HTML_LANG" | default "en"}}
would make the fallback self-contained and not dependent on the extraEnv JavaScript logic.
Similarly, in the JavaScript config injection block (line ~272), parseConfig('{{env "APPSMITH_DEFAULT_HTML_LANG"}}') || "" will resolve to "" rather than "en" when the env var isn't set and the template isn't processed. The triple fallback in AppViewerHtmlTitle (lang || defaultHtmlLang || "en") does save you at runtime, but it means the config carries an empty string that has to be silently corrected downstream.
AppViewerHtmlTitle.tsx — module-level getAppsmithConfigs() call
const { defaultHtmlLang } = getAppsmithConfigs();This is called at module load time, outside any React component or hook. If getAppsmithConfigs() reads from a mutable config store (which it does — it merges ENV_CONFIG and APPSMITH_FEATURE_CONFIGS), this value will be captured once when the module is first imported and won't reflect any subsequent config updates. For an env-var-backed config that doesn't change at runtime this is probably fine in practice, but it's inconsistent with how the rest of the codebase typically calls getAppsmithConfigs() inside the component or a hook. Worth moving it inside the component function to be consistent and future-safe.
GeneralSettings.tsx — no validation before saving
The saveHtmlLang callback does a trimmed === current guard which is good, but there's no check on whether the trimmed value is a plausible BCP 47 code before dispatching the update. A user can type something like "not a language" or paste a long string with spaces, and it will be persisted and then applied to the <html lang> attribute. Invalid lang values don't break anything today, but they degrade accessibility tool behavior and are meaningless for the feature's stated goal.
Even a lightweight check — ensuring the value matches something like /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]+)*$/ before saving, with a small inline error message — would prevent accidental invalid saves. The onBlur/Enter flow means a user can type and walk away without realizing the input was invalid.
PropertyPaneTab.tsx — translate="no" on tabs
This adds translate="no" to the StyledTabs wrapper to prevent auto-translation of tab labels like "Content" and "Style". That's a targeted and reasonable fix for the editor. One thing worth confirming: does StyledTabs (from @appsmith/ads) forward arbitrary HTML attributes to the DOM, or could this silently get swallowed? If it's a styled-component or a custom component that doesn't spread props to the underlying DOM element, the attribute won't reach the browser and the protection won't work.
ApplicationDetailCE.java — no server-side validation
htmlLang is stored as a plain String with no length limit or format constraint. Since this flows from user input all the way into the <html lang> attribute of the served page, it's worth having at least a basic server-side sanitization (trim, max length, reject obviously invalid values) even if client-side validation is added too. Defense in depth applies here.
Overall
The feature direction is good and the code is generally clean. The main things I'd want addressed before merge are the index.html fallback gap (correctness risk for non-Docker deployments) and the missing input validation on the lang setting (both client and server side). The module-level config call in AppViewerHtmlTitle is a minor consistency issue.
|
This PR has not seen activitiy for a while. It will be closed in 7 days unless further activity is detected. |
|
This PR has been closed because of inactivity. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/client/public/index.html`:
- Around line 269-270: The defaultHtmlLang property currently falls back to an
empty string; update the fallback to "en" by changing the expression that sets
defaultHtmlLang (the parseConfig('{{env "APPSMITH_DEFAULT_HTML_LANG"}}') || "")
to use "en" instead of "" so APPSMITH_FEATURE_CONFIGS.defaultHtmlLang will be
"en" when the env var is not set.
In
`@app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx`:
- Around line 152-166: The saveHtmlLang callback currently persists any trimmed
string; update it to validate the value as a BCP 47 language tag before
dispatching updateApplication—use a BCP 47 validator (or a lightweight
regex/Intl.Locale test) to reject invalid tags, normalize the tag (e.g.,
toLowerCase/normalize subtags) only when valid, and return early or surface
validation feedback for invalid input; apply the same BCP 47 validation logic to
the other handler referenced in the review (the similar save function around
lines 498-513) so only valid language tags are persisted.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fba6367b-0f3b-42e6-8c58-0765f996cc92
📒 Files selected for processing (2)
app/client/public/index.htmlapp/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
Resolves review feedback on #41593: - index.html: use a self-contained "en" default for the shell <html lang> and the defaultHtmlLang config fallback, so the default no longer depends on Caddy template substitution (non-Docker/dev deploys) - AppViewerHtmlTitle: read getAppsmithConfigs() inside the component instead of at module load, matching the rest of the codebase - GeneralSettings: validate the HTML language input against a BCP 47 shape before saving, with inline error feedback - ApplicationDetailCE: normalize htmlLang on the JSON/REST write path (trim, lowercase, length-cap, drop non-BCP 47 values) Adds unit tests for the client validator and the server setter. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
/build-deploy-preview skip-tests=true |
|
Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28612469209. |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
app/client/public/index.html (1)
2-2: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRegression: root
<html lang>reverted to static"en".A prior review round fixed this exact line to use
lang='{{env "APPSMITH_DEFAULT_HTML_LANG"}}'so the server-rendered response reflects the configured instance language (confirmed addressed in commit d35b79f). The current code shows<html lang="en" translate="no">, hardcoding"en"again — this undoes that fix and re-introduces the original issue: the first HTML response and loading shell won't advertise the configuredAPPSMITH_DEFAULT_HTML_LANGuntil client-side JS/Helmet runs.🐛 Proposed fix
-<html lang="en" translate="no"> +<html lang='{{env "APPSMITH_DEFAULT_HTML_LANG"}}' translate="no">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/client/public/index.html` at line 2, The root html lang attribute was reverted to a static English value, breaking the server-rendered language signal again. Update the opening <html> tag in index.html to use the APPSMITH_DEFAULT_HTML_LANG template expression instead of hardcoded "en", while preserving the existing translate="no" attribute so the initial response reflects the configured instance language.
🧹 Nitpick comments (2)
app/server/appsmith-server/src/test/java/com/appsmith/server/domains/ApplicationDetailHtmlLangTest.java (1)
37-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd a boundary-length test case.
Only a clearly-too-long value is tested. Consider adding a case exactly at
HTML_LANG_MAX_LENGTH(35 chars, should pass) and one char over (should fail) to lock in the boundary behavior.✅ Suggested boundary test
`@Test` public void setHtmlLang_dropsOverlyLongValues() { String tooLong = "en-" + "x".repeat(40); assertThat(normalized(tooLong)).isNull(); + + String exactlyMax = "en-" + "x".repeat(32); // total length 35 + assertThat(normalized(exactlyMax)).isEqualTo(exactlyMax); + + String oneOverMax = "en-" + "x".repeat(33); // total length 36 + assertThat(normalized(oneOverMax)).isNull(); }As per coding guidelines,
**/*Test.javafiles should contain JUnit unit tests, which this file satisfies; this is a minor coverage suggestion on top of that.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/server/appsmith-server/src/test/java/com/appsmith/server/domains/ApplicationDetailHtmlLangTest.java` around lines 37 - 41, Add boundary coverage to ApplicationDetailHtmlLangTest by extending setHtmlLang_dropsOverlyLongValues with explicit checks around HTML_LANG_MAX_LENGTH: verify a value exactly 35 characters long still passes through normalized(), and verify a value that is 36 characters long is rejected and returns null. Use the existing normalized helper and the HTML_LANG_MAX_LENGTH constant so the boundary behavior is locked in without relying only on an obviously oversized string.Source: Coding guidelines
app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationDetailCE.java (1)
46-62: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winSilent drop on invalid input hides validation errors from API consumers.
Invalid
htmlLangvalues are silently coerced tonullrather than rejected. Clients bypassing the UI (direct REST calls) get a 200 OK with the field silently dropped instead of a validation error, which can mask bugs or misconfigurations.💡 Consider throwing a validation exception instead of silently dropping
public void setHtmlLang(String htmlLang) { if (htmlLang == null) { this.htmlLang = null; return; } String normalized = htmlLang.trim().toLowerCase(); if (normalized.isEmpty() || normalized.length() > HTML_LANG_MAX_LENGTH || !HTML_LANG_PATTERN.matcher(normalized).matches()) { - this.htmlLang = null; - return; + throw new AppsmithException(AppsmithError.INVALID_PARAMETER, "htmlLang"); } this.htmlLang = normalized; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationDetailCE.java` around lines 46 - 62, The setHtmlLang method in ApplicationDetailCE currently normalizes invalid input by assigning null, which hides bad values from API consumers. Update setHtmlLang to reject invalid htmlLang values by throwing the appropriate validation exception instead of silently clearing the field, while still allowing null only when the caller explicitly omits it. Keep the existing normalization and validation checks using HTML_LANG_MAX_LENGTH and HTML_LANG_PATTERN, but route failures through a validation error path so direct REST callers receive feedback rather than a 200 response with a dropped value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationDetailCE.java`:
- Around line 42-45: The current htmlLang normalization only happens in
setHtmlLang(), so Git import and Mongo hydration can still persist invalid
values that AppViewer later renders in the html lang attribute. Add the same
trimming/lowercasing/length and BCP 47 validation on the import/save path in
ApplicationDetailCE, and ensure any persistence flow that bypasses the setter
applies the normalization before ApplicationDetailCE is stored or exposed.
---
Duplicate comments:
In `@app/client/public/index.html`:
- Line 2: The root html lang attribute was reverted to a static English value,
breaking the server-rendered language signal again. Update the opening <html>
tag in index.html to use the APPSMITH_DEFAULT_HTML_LANG template expression
instead of hardcoded "en", while preserving the existing translate="no"
attribute so the initial response reflects the configured instance language.
---
Nitpick comments:
In
`@app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationDetailCE.java`:
- Around line 46-62: The setHtmlLang method in ApplicationDetailCE currently
normalizes invalid input by assigning null, which hides bad values from API
consumers. Update setHtmlLang to reject invalid htmlLang values by throwing the
appropriate validation exception instead of silently clearing the field, while
still allowing null only when the caller explicitly omits it. Keep the existing
normalization and validation checks using HTML_LANG_MAX_LENGTH and
HTML_LANG_PATTERN, but route failures through a validation error path so direct
REST callers receive feedback rather than a 200 response with a dropped value.
In
`@app/server/appsmith-server/src/test/java/com/appsmith/server/domains/ApplicationDetailHtmlLangTest.java`:
- Around line 37-41: Add boundary coverage to ApplicationDetailHtmlLangTest by
extending setHtmlLang_dropsOverlyLongValues with explicit checks around
HTML_LANG_MAX_LENGTH: verify a value exactly 35 characters long still passes
through normalized(), and verify a value that is 36 characters long is rejected
and returns null. Use the existing normalized helper and the
HTML_LANG_MAX_LENGTH constant so the boundary behavior is locked in without
relying only on an obviously oversized string.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f911cd47-2056-4efe-8efb-f8c6c949d106
📒 Files selected for processing (7)
app/client/public/index.htmlapp/client/src/ce/constants/messages.tsapp/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.test.tsapp/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsxapp/client/src/pages/AppViewer/AppViewerHtmlTitle.tsxapp/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationDetailCE.javaapp/server/appsmith-server/src/test/java/com/appsmith/server/domains/ApplicationDetailHtmlLangTest.java
✅ Files skipped from review due to trivial changes (1)
- app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- app/client/src/ce/constants/messages.ts
- app/client/src/pages/AppViewer/AppViewerHtmlTitle.tsx
- app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
|
Deploy-Preview-URL: https://ce-41593.dp.appsmith.com |
Addresses CodeRabbit review comment on #41593: Git import and Mongo hydration write the htmlLang field directly, bypassing setHtmlLang, so an invalid value could still be persisted and served into <html lang>. Extract the normalization into a shared normalizeHtmlLang helper and also apply it in a getHtmlLang override, so any value populated through a setter-bypassing path is normalized before it is serialized to the client or written to a git export. Adds a reflection-based test covering the getter path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
/build-deploy-preview skip-tests=true |
|
Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28616156714. |
|
Deploy-Preview-URL: https://ce-41593.dp.appsmith.com |
|
/build-deploy-preview skip-tests=true recreate=true |
|
Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28618220265. |
The HTML language setting never stuck — blank after switching settings menus and after refresh — due to two bugs: - Server: ApplicationServiceCEImpl.updateApplication rebuilt the merged applicationDetail from only navigationSetting/appPositioning/themeSetting, silently dropping htmlLang before persistence. Now copies htmlLang too. - Client: the UPDATE_APPLICATION reducer merged applicationDetail into a dead top-level state key instead of state.currentApplication, so the saved value never reached the settings panel. Now merges into currentApplication. Also lets users clear the field to revert to the default: normalizeHtmlLang now returns a tri-state (null = absent / leave untouched, "" = explicitly cleared, <tag> = normalized), so an empty value persists as a clear instead of being indistinguishable from "not sent". Tests: domain normalization (incl. clear), a reducer test, and integration tests for persist / clear / sibling-preservation through updateApplicationWithPresets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
/build-deploy-preview skip-tests=true |
|
Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28624605518. |
|
Deploy-Preview-URL: https://ce-41593.dp.appsmith.com |
The App Name field renders a loading spinner while saving; the HTML language field did not. Add an isSavingHtmlLang redux flag mirroring isSavingAppName (reducer + selector) and render TextLoaderIcon on the field while a save is in flight. The flag is set on UPDATE_APPLICATION when applicationDetail.htmlLang is present (a presence check, so clearing the field to "" also shows the spinner) and reset on success/error. No error flag is added: the analogous isErrorSavingNavigationSetting is unread dead state, and the app-name error flag exists only for the inline-rename widget the language field doesn't have. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
/build-deploy-preview skip-tests=true |
|
Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28626096982. |
|
Deploy-Preview-URL: https://ce-41593.dp.appsmith.com |
|
/build-deploy-preview skip-tests=true |
|
Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28839039735. |
|
Deploy-Preview-URL: https://ce-41593.dp.appsmith.com |
subrata71
left a comment
There was a problem hiding this comment.
The changes look good to me. Could you please verify the EE changes by running all CI checks and validating it manually both in App and UI package?
Users building apps in non-English languages (e.g. German) experience corrupted UI text because browsers and translation extensions see and auto-translate page content — sometimes German-to-German, sometimes misinterpreting English UI words like "Content" as the French adjective (translated to "Thrilled").
This PR fixes the problem at three layers:
Immediate defence: Adds translate="no" and to the app shell HTML, editor UI containers (PropertyPane tabs, App Settings), and widget iframe templates. This stops browsers from offering or performing auto-translation.
Per-app language setting: Adds an "HTML Language" field to App Settings > General. App builders can enter a BCP 47 language code (e.g. de, fr, ja) that gets persisted as htmlLang on ApplicationDetail and applied to the published app's attribute at runtime via react-helmet.
Instance-level default: Adds APPSMITH_DEFAULT_HTML_LANG environment variable for self-hosted admins who want all apps on their instance to default to a specific language. Falls back gracefully to "en" when the variable is not set.
Description
Tip
Add a TL;DR when the description is longer than 500 words or extremely technical (helps the content, marketing, and DevRel team).
Please also include relevant motivation and context. List any dependencies that are required for this change. Add links to Notion, Figma or any other documents that might be relevant to the PR.
Fixes #
6642Automation
/ok-to-test tags="@tag.All"
🔍 Cypress test results
Tip
🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/28979471474
Commit: a81679b
Cypress dashboard.
Tags:
@tag.AllSpec:
Wed, 08 Jul 2026 23:34:34 UTC
Communication
Should the DevRel and Marketing teams inform users about this change?
Summary by CodeRabbit
New Features
Behavior
langto the document metadata.translate="no"and Googlenotranslatewhere applicable.Tests