oxc-project/oxc · warning · OxcDiagnostic

Disallow literal text as JSX children

Error message

Disallow literal text as JSX children

What it means

Children-case diagnostic of react/jsx-no-literals (category: restriction). It fires only when noStrings is set to true (default false): string literals used as JSX children — wrapped or unwrapped — are disallowed. The motivation is i18n: user-facing text should flow through an expression such as a translation function instead of being hard-coded as markup text, so strings are auditable in one place.

Source

Thrown at crates/oxc_linter/src/rules/react/jsx_no_literals.rs:29

        JSXAttributeName, JSXAttributeValue, JSXChild, JSXElement, JSXElementName, JSXExpression,
        JSXFragment, JSXMemberExpression, JSXMemberExpressionObject, ModuleExportName, PropertyKey,
    },
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::SymbolId;
use oxc_span::Span;
use oxc_str::CompactStr;

use crate::{
    AstNode,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
    utils::{default_true, is_react_component_name},
};

fn literal_text_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Disallow literal text as JSX children")
        .with_help("Wrap this text in a JSX expression container, such as a call to a translation function.")
        .with_label(span)
}

fn literal_attribute_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Disallow string literals in JSX attributes")
        .with_help("Replace this string literal with a non-literal expression, such as a call to a translation function.")
        .with_label(span)
}

fn restricted_attribute_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Disallow string literals on restricted JSX attributes")
        .with_help("This attribute is listed in `restrictedAttributes`; replace its string literal value with a non-literal expression.")
        .with_label(span)
}

/// The options shared between the top-level config and each `elementOverrides` entry.
#[derive(Debug, Default, Clone, Deserialize, JsonSchema)]

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace the literal with an expression, typically a translation call: <div>{t('hello.world')}</div>
  2. Whitelist intentional literals via allowedStrings: ["•", "—"]
  3. Permit specific elements to keep raw text via elementOverrides: { "kbd": { "allowElement": true } }
  4. If the policy is too strict for now, leave noStrings false (the default) and enable it incrementally per directory

Example fix

// before (noStrings: true)
<div>Hello world</div>

// after
<div>{t('hello.world')}</div>
Defensive patterns

Strategy: validation

Validate before calling

npx oxlint -D react/jsx-no-literals src/  # with noStrings: true in .oxlintrc.json

Prevention

When it happens

Trigger: Config { "noStrings": true } plus <div>Hello world</div> (unwrapped) or <div>{'Hello world'}</div> (wrapped literal). Exceptions: strings listed in allowedStrings, and elements opted out via elementOverrides with allowElement: true.

Common situations: Enabling the rule on a legacy codebase full of hard-coded copy before an internationalization effort; teams using i18next/Lingua-style t() functions wanting to guarantee no untranslated strings; accidental reports for punctuation/symbols that should go into allowedStrings.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/be80d0e81b1b85f4. Report an issue: GitHub.