Skip to content

feat: allow customization of HTML lang attribute #41593

Open
salevine wants to merge 13 commits into
releasefrom
feat/6642/enable-lang-tag
Open

feat: allow customization of HTML lang attribute #41593
salevine wants to merge 13 commits into
releasefrom
feat/6642/enable-lang-tag

Conversation

@salevine

@salevine salevine commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

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 #6642

Automation

/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.All
Spec:


Wed, 08 Jul 2026 23:34:34 UTC

Communication

Should the DevRel and Marketing teams inform users about this change?

  • Yes
  • No

Summary by CodeRabbit

  • New Features

    • Added an “HTML language” setting to General Settings (BCP 47), with validation, persistence, and an environment-configurable default.
  • Behavior

    • Published apps now apply the chosen (or default) HTML lang to the document metadata.
    • App pages, loading screens, and embedded/iframe content now opt out of automatic translation via translate="no" and Google notranslate where applicable.
  • Tests

    • Added unit tests covering HTML language input validation and normalization.

…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
@salevine salevine added the ok-to-test Required label for CI label Mar 6, 2026
@salevine salevine requested review from a team and sharat87 as code owners March 6, 2026 02:05
@salevine salevine requested review from vivek-appsmith and removed request for a team March 6, 2026 02:05
@github-actions github-actions Bot added the Enhancement New feature or request label Mar 6, 2026
@coderabbitai

coderabbitai Bot commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds HTML language propagation and translation suppression across public pages, runtime config, settings UI, viewer rendering, and server application detail data.

Changes

HTML language propagation and translation suppression

Layer / File(s) Summary
Public HTML and env injection
app/client/public/404.html, app/client/public/index.html, deploy/docker/fs/opt/appsmith/templates/loading.html, deploy/docker/fs/opt/appsmith/caddy-reconfigure.mjs
Adds translate="no" and Google notranslate metadata in public HTML, and exports APPSMITH_DEFAULT_HTML_LANG into the generated environment.
Runtime config plumbing
app/client/src/ce/configs/index.ts, app/client/src/ce/configs/types.ts, app/client/public/index.html
Carries defaultHtmlLang through injected config, runtime config resolution, and feature config bootstrapping.
App language setting UI
app/client/src/ce/constants/messages.ts, app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx, app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.test.ts
Adds the HTML language field copy, validation, editor input, save behavior, and validation tests.
Viewer html lang wiring
app/client/src/pages/AppViewer/AppViewerHtmlTitle.tsx, app/client/src/pages/AppViewer/index.tsx
Passes the application language into the viewer HTML title path and applies the default fallback language.
Editor and widget translation suppression
app/client/src/pages/AppIDE/components/AppSettings/AppSettings.tsx, app/client/src/pages/Editor/PropertyPane/PropertyPaneTab.tsx, app/client/src/widgets/CustomWidget/component/index.tsx, app/client/src/widgets/ExternalWidget/component/index.tsx, app/client/src/widgets/wds/WDSCustomWidget/component/createHtmlTemplate.ts
Adds translate="no" to editor tabs and widget-rendered HTML roots.
Server application detail htmlLang
app/client/src/ce/api/ApplicationApi.tsx, app/client/src/entities/Application/types.ts, app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationDetailCE.java, app/server/appsmith-server/src/test/java/com/appsmith/server/domains/ApplicationDetailHtmlLangTest.java
Extends application detail payloads and server application detail data with htmlLang, including normalization and test coverage.

Estimated code review effort: 4 (Complex) | ~45 minutes

Poem

A language tag found its new home,
Through configs and viewers it’ll roam.
No-translate signs stand near,
So pages stay clear,
And apps speak the way they were sown.

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning #6642 requests a sidebar widget, but this PR instead changes HTML lang and translation behavior. Implement the sidebar widget requested by #6642, or update the linked issue if the intended scope has changed.
Out of Scope Changes check ⚠️ Warning Most changes are unrelated to #6642 and introduce broader HTML lang and translation-suppression work. Move the HTML lang and translation-suppression work to a separate PR, or retarget this PR to the sidebar widget scope.
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding customizable HTML lang support.
Description check ✅ Passed The description includes motivation, issue reference, automation notes, Cypress results, and communication section, matching the template well.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/6642/enable-lang-tag

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between d18802b and 6f24fce.

📒 Files selected for processing (18)
  • app/client/public/404.html
  • app/client/public/index.html
  • app/client/src/ce/api/ApplicationApi.tsx
  • app/client/src/ce/configs/index.ts
  • app/client/src/ce/configs/types.ts
  • app/client/src/ce/constants/messages.ts
  • app/client/src/entities/Application/types.ts
  • app/client/src/pages/AppIDE/components/AppSettings/AppSettings.tsx
  • app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
  • app/client/src/pages/AppViewer/AppViewerHtmlTitle.tsx
  • app/client/src/pages/AppViewer/index.tsx
  • app/client/src/pages/Editor/PropertyPane/PropertyPaneTab.tsx
  • app/client/src/widgets/CustomWidget/component/index.tsx
  • app/client/src/widgets/ExternalWidget/component/index.tsx
  • app/client/src/widgets/wds/WDSCustomWidget/component/createHtmlTemplate.ts
  • app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationDetailCE.java
  • deploy/docker/fs/opt/appsmith/caddy-reconfigure.mjs
  • deploy/docker/fs/opt/appsmith/templates/loading.html

Comment thread app/client/public/index.html
@salevine salevine added ok-to-test Required label for CI and removed ok-to-test Required label for CI labels Mar 6, 2026
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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
app/client/public/index.html (1)

2-2: ⚠️ Potential issue | 🟠 Major

Keep the "en" fallback at the render site.

Line 2 and Lines 271-272 still collapse to an empty value when APPSMITH_DEFAULT_HTML_LANG is unset, so the first HTML response can ship lang="" and the client config can expose defaultHtmlLang: "". 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

📥 Commits

Reviewing files that changed from the base of the PR and between 6f24fce and d35b79f.

📒 Files selected for processing (1)
  • app/client/public/index.html

@salevine

salevine commented Mar 8, 2026

Copy link
Copy Markdown
Contributor Author

/build-deploy-preview skip-tests=true

@github-actions

github-actions Bot commented Mar 8, 2026

Copy link
Copy Markdown

Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/22827220661.
Workflow: On demand build Docker image and deploy preview.
skip-tests: true.
env: ``.
PR: 41593.
recreate: .

@github-actions

github-actions Bot commented Mar 8, 2026

Copy link
Copy Markdown

Deploy-Preview-URL: https://ce-41593.dp.appsmith.com

@vivek-appsmith vivek-appsmith requested review from sondermanish and subrata71 and removed request for vivek-appsmith March 9, 2026 10:13

@subrata71 subrata71 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.tsxtranslate="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.

Comment thread app/client/public/index.html Outdated
@github-actions

Copy link
Copy Markdown

This PR has not seen activitiy for a while. It will be closed in 7 days unless further activity is detected.

@github-actions github-actions Bot added the Stale label Mar 23, 2026
@github-actions

Copy link
Copy Markdown

This PR has been closed because of inactivity.

@github-actions github-actions Bot closed this Mar 31, 2026
@amelia-c0n amelia-c0n reopened this Apr 30, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between d35b79f and b29be59.

📒 Files selected for processing (2)
  • app/client/public/index.html
  • app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx

Comment thread app/client/public/index.html Outdated
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>
@sebastianiv21

Copy link
Copy Markdown
Contributor

/build-deploy-preview skip-tests=true

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28612469209.
Workflow: On demand build Docker image and deploy preview.
skip-tests: true.
env: ``.
PR: 41593.
recreate: .
base-image-tag: .

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
app/client/public/index.html (1)

2-2: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Regression: 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 configured APPSMITH_DEFAULT_HTML_LANG until 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 value

Add 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.java files 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 win

Silent drop on invalid input hides validation errors from API consumers.

Invalid htmlLang values are silently coerced to null rather 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

📥 Commits

Reviewing files that changed from the base of the PR and between b3f66c7 and eeac7e6.

📒 Files selected for processing (7)
  • app/client/public/index.html
  • app/client/src/ce/constants/messages.ts
  • app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.test.ts
  • app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
  • app/client/src/pages/AppViewer/AppViewerHtmlTitle.tsx
  • app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ApplicationDetailCE.java
  • app/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

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

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>
@sebastianiv21

Copy link
Copy Markdown
Contributor

/build-deploy-preview skip-tests=true

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28616156714.
Workflow: On demand build Docker image and deploy preview.
skip-tests: true.
env: ``.
PR: 41593.
recreate: .
base-image-tag: .

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploy-Preview-URL: https://ce-41593.dp.appsmith.com

@sebastianiv21

Copy link
Copy Markdown
Contributor

/build-deploy-preview skip-tests=true recreate=true

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28618220265.
Workflow: On demand build Docker image and deploy preview.
skip-tests: true.
env: ``.
PR: 41593.
recreate: true.
base-image-tag: .

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>
@sebastianiv21

Copy link
Copy Markdown
Contributor

/build-deploy-preview skip-tests=true

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28624605518.
Workflow: On demand build Docker image and deploy preview.
skip-tests: true.
env: ``.
PR: 41593.
recreate: .
base-image-tag: .

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

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>
@sebastianiv21

Copy link
Copy Markdown
Contributor

/build-deploy-preview skip-tests=true

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28626096982.
Workflow: On demand build Docker image and deploy preview.
skip-tests: true.
env: ``.
PR: 41593.
recreate: .
base-image-tag: .

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploy-Preview-URL: https://ce-41593.dp.appsmith.com

@github-actions github-actions Bot removed the Stale label Jul 3, 2026
@sebastianiv21

Copy link
Copy Markdown
Contributor

/build-deploy-preview skip-tests=true

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/28839039735.
Workflow: On demand build Docker image and deploy preview.
skip-tests: true.
env: ``.
PR: 41593.
recreate: .
base-image-tag: .

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Deploy-Preview-URL: https://ce-41593.dp.appsmith.com

@subrata71 subrata71 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement New feature or request ok-to-test Required label for CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants