ScreenshotNeo

BlogHow-to

How to test Hindi and other Indian language layouts in Chromatic

Test Indian-language layouts in Chromatic with realistic Storybook stories, reliable font loading, locale modes, and responsive viewports.

By the ScreenshotNeo team4 October 20268 min read

To test Hindi and other Indian-language layouts in Chromatic, render realistic translated content in Storybook, capture it under locale and viewport modes, and make sure the font that covers each script has loaded before capture. Review snapshots for missing or substituted glyphs, wrapping, clipping, overflow, and changes in component height. Set text direction from the actual locale and UI requirements; a non-Latin script does not by itself imply right-to-left layout.

Chromatic captures rendered Storybook stories and compares them with baselines. Locale variations need to be represented as test conditions, and each configured mode has its own baseline and approval workflow. The setup verifies your project’s rendered output; it does not guarantee that a particular font, asset pipeline, or translation will work correctly. [Chromatic Modes](https://www.chromatic.com/docs/modes/) · [Storybook visual testing](https://storybook.js.org/docs/9/writing-tests/visual-testing)

1. Add realistic localized stories

Start with components where translation changes are likely to affect layout: navigation, buttons, forms, alerts, cards, tables, dialogs, and headings. Use real or representative Hindi and other Indian-language strings, including the longest labels and content combinations your interface supports. Include empty, error, loading, and validation states where their text differs by locale.

For React applications using i18next, Storybook’s recipe shows how to expose the locale as a Storybook global, connect the selected value to the translation provider or decorator, and update the document direction when the language changes. Adapt its pattern to your framework and translation library. [Storybook React i18next recipe](https://storybook.js.org/recipes/react-i18next)

// .storybook/preview.ts — illustrative React/i18next setup
import type { Preview } from '@storybook/react';
import i18n from '../src/i18n';

const preview: Preview = {
  globalTypes: {
    locale: {
      description: 'Active UI locale',
      toolbar: {
        title: 'Locale',
        items: [
          { value: 'en', title: 'English' },
          { value: 'hi', title: 'Hindi' },
          { value: 'bn', title: 'Bengali' },
          { value: 'ta', title: 'Tamil' },
        ],
      },
    },
  },
  initialGlobals: { locale: 'en' },
  decorators: [
    (Story, context) => {
      const locale = context.globals.locale;
      i18n.changeLanguage(locale);
      document.documentElement.lang = locale;
      // Determine direction from your i18n configuration and UI needs.
      document.documentElement.dir = i18n.dir(locale);
      return Story();
    },
  ],
};

export default preview;

This is a starting pattern, not a complete drop-in configuration for every Storybook version or application. Confirm that changing the global causes translations to update before capture. Use your app’s actual direction configuration; do not assign RTL merely because the language is localized or uses a non-Latin script.

2. Configure Chromatic locale modes

Use Chromatic Modes to capture the global combinations you need, such as Hindi with a narrow viewport or Bengali with a particular theme. Keep the matrix targeted: include locales that exercise different translation and script behavior, and widths where the component is most likely to wrap or overflow. Each mode has its own snapshot baseline. [Chromatic Modes](https://www.chromatic.com/docs/modes/)

If the story depends on browser locale behavior—such as browser-driven formatting or server responses—configure a browser locale mode too. Chromatic’s browser locale option changes navigator.language and the Accept-Language request header. A translated React tree alone does not necessarily exercise those browser behaviors. [Browser options in Modes](https://www.chromatic.com/docs/modes/browser-options/)

3. Ensure the required font is available before capture

Check that your selected font actually includes the glyphs used by your localized strings. A font-loading strategy documented for one script is not proof that the same font covers Hindi or another Indian script. Test the exact family, weights, and characters your interface renders.

Chromatic documents several ways to make font loading reliable: preload fonts from Storybook’s preview-head.html, serve local font files in the test environment, or use a Storybook loader with the browser Font Loading API. Choose an approach compatible with how your app serves its fonts, then confirm the font is loaded before snapshots are taken. [Chromatic font loading](https://www.chromatic.com/docs/font-loading/)

// Example Storybook loader: wait for a known font before rendering.
export const loaders = [async () => {
  await document.fonts.load('400 16px "Your Devanagari Font"');
  await document.fonts.ready;
  return {};
}];

Replace the family with a font configured and served by your project. If you use several script-specific or weight-specific files, ensure the relevant faces are requested and ready. A late font swap can change glyph shapes, line breaks, and element dimensions, which makes captures unreliable.

4. Capture the widths that expose layout problems

Include the responsive widths that matter to your design, especially narrow widths where longer translations may wrap. Configure Storybook viewports or Chromatic Modes to vary viewport settings, and pair important widths with the locales that produce the densest content. [Chromatic viewports](https://www.chromatic.com/docs/viewports/) · [Chromatic Modes](https://www.chromatic.com/docs/modes/)

At each width, inspect whether labels wrap as intended, controls remain usable, text stays within its container, and translated content changes component height in a way the surrounding layout can accommodate. Storybook notes that longer localized strings can cause overflow; use the strings your product actually ships rather than assuming every translation has similar length. [Storybook React i18next recipe](https://storybook.js.org/recipes/react-i18next)

5. Review snapshots as rendering evidence

Chromatic compares captured pixels with an existing baseline and highlights visual differences. For each difference, inspect the rendered story and decide whether it represents an expected translation change or a defect. Look specifically for tofu boxes or missing glyphs, unexpected fallback fonts, changed line breaks, clipping, horizontal overflow, and component-height or alignment shifts. [Storybook visual testing](https://storybook.js.org/docs/9/writing-tests/visual-testing) · [Chromatic snapshots](https://www.chromatic.com/docs/snapshots/)

Approve a baseline only after checking the affected locale, font, and viewport. If a difference appears inconsistently between captures, investigate font readiness, external font availability, and other rendering dependencies before treating the snapshot as stable.

6. Build a useful language-layout matrix

Test dimension What to configure or inspect
Locale and translation Story global or equivalent selects the intended translation resources and locale-sensitive behavior.
Script and font The loaded family and weight contain the glyphs actually used by each story.
Browser locale Vary browser locale when the app depends on navigator.language or Accept-Language.
Direction Set document or component direction according to the locale and actual interface requirements.
Viewport and content Capture relevant responsive widths with realistic, sufficiently long localized strings.
Baseline review Classify differences as expected localization changes or rendering and layout regressions.

Keep the matrix small enough to review and broad enough to cover distinct risks. A useful selection is based on your app’s scripts, font files, locale-sensitive behavior, longest content, and responsive breakpoints—not on a general assumption that every Indian language behaves the same.

Common problems and fixes

Symptom Likely cause What to check
Boxes or missing characters The active font lacks one or more required glyphs, or the font file did not load. Verify glyph coverage for the actual string and confirm the expected font face is available in the capture environment.
Snapshots change between runs A font or other rendering dependency is not ready at capture time. Preload or locally serve the font, or wait with the Font Loading API before rendering the story.
The toolbar locale changes but text does not The global is not connected to the translation provider, or the story does not rerender on language changes. Check the decorator/provider wiring and verify the selected locale changes the rendered story.
Text overflows only at narrow widths The test uses too few responsive widths or unrealistically short strings. Add the affected width and representative long translations; inspect wrapping and container constraints.
Formatting differs from the expected locale The story translation changed, but the browser locale did not, or locale-sensitive formatting uses a separate setting. Use browser locale mode where needed and check the formatting code’s locale input.
Direction is wrong Direction was inferred from script or hard-coded independently of locale behavior. Set direction from the app’s locale configuration and the component’s actual requirements.
A baseline shows broad visual changes The font, translation, viewport, or mode changed across many stories. Review the selected mode and rendered output before accepting; identify whether the change is expected or a regression.

Performance, reliability, and cost considerations

Every additional locale and viewport mode adds snapshots to capture and review. Prioritize combinations that cover different scripts, font faces, long strings, browser-locale behavior, and breakpoint risks. Font readiness improves reliability because it avoids capturing fallback text before the intended font is ready. Keep fonts and other required assets available to the capture environment.

Chromatic’s cited documentation describes configuration and visual comparison behavior; it does not establish that any particular project’s Indian-language font assets or translations will render correctly. Confirm support by inspecting your own captures. Consult Chromatic’s current plan and usage information for pricing and limits; no pricing figures are needed to configure this workflow.

Or skip the browser setup

If you need a clean screenshot of a page without setting up browser capture yourself, ScreenshotNeo is a website screenshot API and MCP server for developers. Its one-call API accepts a URL and returns an image or PDF. For example, capture a localized page URL with cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for request options. ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for 1,000 free screenshots a month, with no card required.

FAQ

Does Chromatic choose a suitable font for Hindi automatically?

The cited guidance recommends selecting a font that covers the target script and making its loading deterministic. Check the font and strings used by your project in captured stories.

Should every localized language use RTL?

No. Choose direction from the locale and interface requirements. Script and direction are separate concerns.

Do I need browser locale modes if I already switch translations in Storybook?

Only when you also need to test browser locale behavior, such as navigator.language or the Accept-Language request header. A translation global alone does not set those browser values.

Can a passing snapshot prove every translation renders correctly?

A snapshot covers the stories, modes, fonts, and viewports you configured. Unrepresented strings and conditions still need coverage.