Skip to content

Conversation

@Lakshit-Gupta
Copy link

@Lakshit-Gupta Lakshit-Gupta commented Jan 30, 2026

Pull Request: Add locale-switcher-widget Community Project

Description

Adds a reusable locale switcher component library for Lingo.dev Compiler projects.

Problem Solved

Every Lingo.dev Compiler project needs a locale switcher UI, but developers currently build it from scratch each time. This library provides production-ready components that integrate seamlessly with Lingo.dev.

Features

  • Three variants: dropdown, flags grid, and minimal
  • 30+ pre-configured locales with native names and emoji flags
  • Full TypeScript support and Lingo.dev Compiler integration
  • ARIA-compliant accessibility with dark mode support
  • Working demo app showcasing all variants with Vite + Lingo.dev Compiler
  • Comprehensive documentation and usage examples
  • Unit tests for all components (Vitest)

What's Included

community/locale-switcher-widget/
├── src/
│   ├── components/         # Three component variants
│   ├── test/              # Unit tests with Vitest
│   ├── types.ts           # TypeScript definitions
│   ├── utils.ts           # 30+ locale mappings
│   ├── styles.css         # Component styles
│   └── index.ts           # Public exports
├── demo/                  # Full working demo
│   ├── src/App.tsx        # Demo showcasing all variants
│   └── vite.config.ts     # With Lingo.dev Compiler
└── README.md             # Comprehensive docs

Total: 29 files, 8,153 lines of code

Component Variants

Dropdown Variant

Perfect for header navigation with many locales.

Flags Grid Variant

Visual flag selector for prominent placement.

Minimal Variant

Compact button that cycles through locales.

Usage Example

import { useLocale } from '@lingo.dev/compiler/react';
import { LocaleSwitcher, buildLocaleOptions } from './locale-switcher';

function App() {
  const { locale, setLocale, config } = useLocale();

  return (
    <LocaleSwitcher
      currentLocale={locale}
      locales={buildLocaleOptions(config.targetLocales)}
      onLocaleChange={setLocale}
      variant="dropdown"
    />
  );
}

PR Checklist

  • Linked issue: N/A (community contribution)
  • Conventional commit title: feat: add locale-switcher-widget community project
  • Tests included: Unit tests for all three component variants
  • Changeset added: .changeset/locale-switcher-widget.md
  • Follows community guidelines:
  • kebab-case naming
  • Own README.md with setup instructions
  • Standalone project structure
  • Signed commits: All commits are signed
  • High quality: TypeScript, accessibility, dark mode, comprehensive docs

Community Value

Before: Every developer spends 30-60 minutes building their own locale switcher

After: Import LocaleSwitcher and done in 2 minutes

This is a genuinely useful contribution that every Lingo.dev Compiler user will benefit from. It demonstrates best practices and provides a template for building accessible, production-ready i18n components.

Demo

The demo/ folder contains a fully functional Vite app that showcases all three variants with live translation using Lingo.dev Compiler.

Additional Notes

Also includes comprehensive AI agent instructions in .github/copilot-instructions.md to help future contributors understand the codebase architecture and conventions.


Ready for review! This contribution follows all guidelines and provides immediate value to the Lingo.dev community.

Summary by CodeRabbit

  • New Features

    • Added a reusable locale switcher widget with three UI variants (dropdown, flags grid, minimal), TypeScript types, and 30+ pre-configured locales.
  • Documentation

    • Added comprehensive docs, setup guides, and a PR/contributor checklist.
  • Demo

    • Included a demo app showcasing all variants and locale switching.
  • Style

    • Added full styling with dark mode and responsive behaviour.
  • Tests

    • Added unit tests covering all switcher variants and interactions.

✏️ Tip: You can customize this high-level summary in your review settings.

Add reusable locale switcher component library for Lingo.dev Compiler projects.

Features:

- Three variants: dropdown, flags grid, and minimal

- 30+ pre-configured locales with native names and flags

- Full TypeScript support and Lingo.dev Compiler integration

- Accessible (ARIA-compliant) with dark mode support

- Working demo app with Vite

Also adds comprehensive AI coding agent instructions in .github/copilot-instructions.md
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 30, 2026

📝 Walkthrough

Walkthrough

Adds a new community-contributed locale switcher library: React components (dropdown, flags, minimal), TypeScript types, locale utilities, styles with dark mode, tests, a Vite demo app, package tooling, and documentation.

Changes

Cohort / File(s) Summary
Docs & Governance
.changeset/locale-switcher-widget.md, .github/copilot-instructions.md, PR_DESCRIPTION.md, community/locale-switcher-widget/README.md
Adds changeset, contributor/agent guidance, PR description, and comprehensive README documenting usage, variants, demo, and contribution guidance.
Package & Build Config
community/locale-switcher-widget/package.json, community/locale-switcher-widget/vite.config.ts, community/locale-switcher-widget/tsconfig.json, community/locale-switcher-widget/demo/package.json, community/locale-switcher-widget/demo/vite.config.ts, community/locale-switcher-widget/demo/tsconfig.json
Introduces library and demo manifests, Vite configs (library + demo), TS configs, build/test/typegen settings, and export map entries.
Source: Components & API
community/locale-switcher-widget/src/index.ts, community/locale-switcher-widget/src/types.ts, community/locale-switcher-widget/src/utils.ts, community/locale-switcher-widget/src/components/...
Adds public API surface, TS interfaces (LocaleOption, LocaleSwitcherProps), DEFAULT_LOCALE_MAP and helper functions, plus components: LocaleSwitcher, DropdownSwitcher, FlagsSwitcher, MinimalSwitcher.
Styling
community/locale-switcher-widget/src/styles.css
Adds comprehensive CSS for all variants, utility classes, positioning, focus/hover states, and prefers-color-scheme dark-mode rules.
Tests
community/locale-switcher-widget/src/test/setup.ts, community/locale-switcher-widget/src/test/DropdownSwitcher.test.tsx, community/locale-switcher-widget/src/test/FlagsSwitcher.test.tsx, community/locale-switcher-widget/src/test/MinimalSwitcher.test.tsx
Adds Vitest/React Testing Library setup and unit tests covering rendering, interactions, and accessibility states for each switcher variant.
Demo App
community/locale-switcher-widget/demo/index.html, community/locale-switcher-widget/demo/src/main.tsx, community/locale-switcher-widget/demo/src/App.tsx, community/locale-switcher-widget/demo/src/*.css
Adds a Vite + React demo using LingoProvider, rendering the three switcher variants, code previews, translation demo panel, and responsive theming.
Packaging & Ignoring
community/locale-switcher-widget/.gitignore, community/locale-switcher-widget/.npmignore, .vscode/settings.json
Adds ignore rules for node/dist/editor artifacts, npm publish ignores, and a small VS Code setting tweak.
Misc
community/locale-switcher-widget/demo/package.json, community/locale-switcher-widget/demo/*
Demo-specific package and assets to run/preview the example locally.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

community

Suggested reviewers

  • sumitsaurabh927
  • vrcprl

Poem

🐰 I hopped in with code and a map of the globe,
Three switchers bundled in one tidy wardrobe.
Flags, dropdown, and tiny-next-tap delight,
Tests snugly tucked, dark mode glowing at night.
Hop, click, translate — the world’s in my byte! 🌍✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description provides comprehensive coverage with a summary, features, project structure, usage example, and checklist. However, it deviates significantly from the template format—omitting the 'Changes' section, 'Testing' checklist with test descriptions, 'Visuals' section (with screenshots/demos), and the standard format for issue linking. Restructure the description to match the template format: add a concise 'Changes' bullet list, complete the 'Testing' checklist with specific test descriptions and a confirmation that tests pass, and clarify issue linkage or confirm N/A for community contributions.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change—adding a new community locale-switcher-widget project. It is specific, related to the core of the changeset, and follows conventional commit format.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🤖 Fix all issues with AI agents
In @.changeset/locale-switcher-widget.md:
- Around line 1-6: The changeset frontmatter is empty so the package won't be
released; update .changeset/locale-switcher-widget.md by adding a YAML
frontmatter block that includes the package name
"@lingo-community/locale-switcher" and the bump type (e.g., "minor" or "patch")
so the changeset will trigger a release — ensure the frontmatter is valid YAML
(surrounded by ---) and contains the package key with the chosen version bump.

In @.github/copilot-instructions.md:
- Around line 75-89: The fenced code block showing the project tree (the block
that begins with the lines "packages/         # Core product packages" and the
opening ``` marker) is missing a language tag which triggers MD040; edit that
opening fence to include a language hint (for example change ``` to ```text) so
the block becomes ```text and leave the closing ``` unchanged to satisfy the
linter.

In `@community/locale-switcher-widget/package.json`:
- Around line 6-25: The package.json scripts are stubs; wire them to the real
tools so artifacts are produced: update "dev" to run the Vite dev server (e.g.,
"vite"), update "build" to run Vite's production build (e.g., "vite build") so
./dist is generated, update "preview" to run Vite preview (e.g., "vite preview")
and update "typecheck" to run tsc against the package tsconfig (e.g., "tsc -p
tsconfig.json --noEmit" or "tsc -p tsconfig.json --emitDeclarationOnly" if you
want only types). Ensure these scripts reference the existing vite.config.ts and
tsconfig.json and produce the dist/ artifacts and declaration files as intended.

In `@community/locale-switcher-widget/README.md`:
- Around line 98-107: The markdown table separator row between the header and
body is missing spaces around the pipe characters causing markdownlint MD060;
update the separator row (the line under the header that currently looks like
"|------|------|---------|-------------|") to include spaces around each pipe
(e.g. "| --- | --- | --- | --- |") so it matches the header row for the props
such as `currentLocale`, `locales`, `onLocaleChange`, `variant`, `className`,
`showLabels`, and `position`; ensure the separator columns align with the header
count and keep the same number of dashes per column.
- Around line 176-190: The README.md's file-tree fenced code block is missing a
language specifier (markdownlint MD040); update the opening fence for the tree
block in the locale-switcher-widget README (the block showing
"locale-switcher-widget/ ├── src/ ...") to include a language identifier such as
"text" (i.e., change ``` to ```text) so the markdown linter recognizes the code
block language.

In `@community/locale-switcher-widget/src/components/DropdownSwitcher.tsx`:
- Around line 38-69: The buttons in DropdownSwitcher (the trigger button and
each locale option in the map) currently lack explicit types and will default to
type="submit" if placed inside a form; update the trigger button (the element
with class "lingo-switcher-trigger" that toggles isOpen) and the option buttons
inside the locales.map (class "lingo-switcher-option" that calls handleSelect)
to include type="button" so clicks do not submit enclosing forms.
- Around line 16-17: currentOption can be undefined when locales is an empty
array which causes accessing currentOption.flag/label to crash; in
DropdownSwitcher (where locales, currentLocale and currentOption are defined)
add a guard: if locales is empty return null (or render a safe fallback) or
compute currentOption as locales.find(l => l.code === currentLocale) || { code:
currentLocale, label: 'Unknown', flag: null } so downstream access is
safe—update any rendering logic that uses currentOption.flag/label to handle
null/undefined values accordingly.

In `@community/locale-switcher-widget/src/components/FlagsSwitcher.tsx`:
- Around line 13-29: The component currently exposes ARIA radio semantics
without implementing the required keyboard roving/arrow behavior; update the
container from role="radiogroup" to role="group" and switch each button from
role="radio" + aria-checked to using aria-pressed (true/false) to reflect toggle
state, keeping the existing onLocaleChange handler and button focusability;
ensure you remove or replace aria-checked on the button and set
aria-pressed={locale.code === currentLocale} so the UX matches the implemented
click-only behavior (references: locales, currentLocale, onLocaleChange,
showLabels, className).

In `@community/locale-switcher-widget/src/components/MinimalSwitcher.tsx`:
- Around line 11-22: The component currently assumes locales is non-empty; guard
by checking locales.length and currentIndex before computing nextLocale in
MinimalSwitcher: if locales.length === 0 return null (or render a disabled
button), and handle currentIndex === -1 by defaulting to 0; ensure the code that
references nextLocale (onLocaleChange(nextLocale.code), nextLocale.flag,
nextLocale.code, nextLocale.label) only runs when nextLocale is defined to avoid
runtime crashes.

In `@community/locale-switcher-widget/src/test/DropdownSwitcher.test.tsx`:
- Around line 6-8: Add a beforeEach that clears the shared mock to avoid tests
leaking call history: in DropdownSwitcher.test.tsx add a beforeEach(() => {
vi.clearAllMocks(); }) or specifically beforeEach(() => {
mockOnLocaleChange.mockClear(); }) so the vi.fn() mockOnLocaleChange is reset
before each test; reference the mockOnLocaleChange symbol used alongside the
describe('DropdownSwitcher', ...) block.

In `@community/locale-switcher-widget/src/test/MinimalSwitcher.test.tsx`:
- Around line 6-8: The mockOnLocaleChange vi.fn() is shared across tests and
must be cleared to avoid cross-test interference; add a beforeEach in
MinimalSwitcher.test.tsx that calls mockOnLocaleChange.mockClear() (or
mockReset()) before each test so assertions like toHaveBeenCalledWith only see
calls from the current test and not accumulated calls from prior tests.
🧹 Nitpick comments (2)
community/locale-switcher-widget/src/components/LocaleSwitcher.tsx (1)

1-1: Unused React import.

With the new JSX transform ("jsx": "react-jsx" in tsconfig), explicit React imports are not needed for JSX. This import is unused and can be removed.

Proposed fix
-import React from 'react';
 import { LocaleSwitcherProps } from '../types';
community/locale-switcher-widget/src/utils.ts (1)

44-45: Avoid returning shared objects from DEFAULT_LOCALE_MAP.

Consumers can mutate the returned LocaleOption and inadvertently alter the shared map. Returning a shallow copy prevents that.

♻️ Suggested fix
 export function getLocaleOption(code: string): LocaleOption {
-  return DEFAULT_LOCALE_MAP[code] || { code, label: code, flag: '🌐' };
+  const option = DEFAULT_LOCALE_MAP[code];
+  return option ? { ...option } : { code, label: code, flag: '🌐' };
 }

Comment on lines 1 to 6
---
---

Add locale-switcher-widget community contribution.

A reusable locale switcher component library for Lingo.dev Compiler projects with three variants (dropdown, flags grid, minimal), 30+ pre-configured locales, TypeScript support, and accessibility features.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, find the actual package.json for locale-switcher-widget
find . -path "*/locale-switcher-widget/package.json" -type f

Repository: lingodotdev/lingo.dev

Length of output: 112


🏁 Script executed:

#!/bin/bash
# Also search for any package.json files containing locale-switcher or similar
fd "package\.json" | xargs grep -l "locale-switcher" 2>/dev/null || echo "No matches found"

Repository: lingodotdev/lingo.dev

Length of output: 161


🏁 Script executed:

#!/bin/bash
# Check the content of the changeset file
cat -n .changeset/locale-switcher-widget.md

Repository: lingodotdev/lingo.dev

Length of output: 373


🏁 Script executed:

#!/bin/bash
# Get the package name from package.json
cat community/locale-switcher-widget/package.json | grep -A 1 '"name"'

Repository: lingodotdev/lingo.dev

Length of output: 132


Changeset frontmatter is empty.
The package release entry is missing. Add @lingo-community/locale-switcher and the appropriate bump type to the frontmatter for the package to be released.

Example fix
 ---
+"@lingo-community/locale-switcher": minor
 ---
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
---
---
Add locale-switcher-widget community contribution.
A reusable locale switcher component library for Lingo.dev Compiler projects with three variants (dropdown, flags grid, minimal), 30+ pre-configured locales, TypeScript support, and accessibility features.
---
"@lingo-community/locale-switcher": minor
---
Add locale-switcher-widget community contribution.
A reusable locale switcher component library for Lingo.dev Compiler projects with three variants (dropdown, flags grid, minimal), 30+ pre-configured locales, TypeScript support, and accessibility features.
🤖 Prompt for AI Agents
In @.changeset/locale-switcher-widget.md around lines 1 - 6, The changeset
frontmatter is empty so the package won't be released; update
.changeset/locale-switcher-widget.md by adding a YAML frontmatter block that
includes the package name "@lingo-community/locale-switcher" and the bump type
(e.g., "minor" or "patch") so the changeset will trigger a release — ensure the
frontmatter is valid YAML (surrounded by ---) and contains the package key with
the chosen version bump.

Comment on lines 98 to 107
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `currentLocale` | `string` | **required** | Current active locale code |
| `locales` | `LocaleOption[]` | **required** | Array of available locales |
| `onLocaleChange` | `(locale: string) => void` | **required** | Callback fired on locale change |
| `variant` | `'dropdown' \| 'flags' \| 'minimal'` | `'dropdown'` | Display variant |
| `className` | `string` | - | Custom CSS class |
| `showLabels` | `boolean` | `true` | Show locale labels |
| `position` | `'top' \| 'bottom'` | `'bottom'` | Dropdown position |

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix table separator spacing (markdownlint MD060).
Line 99 lacks spaces around pipes in the separator row.

✍️ Proposed fix
-|------|------|---------|-------------|
+| ---- | ---- | ------- | ----------- |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `currentLocale` | `string` | **required** | Current active locale code |
| `locales` | `LocaleOption[]` | **required** | Array of available locales |
| `onLocaleChange` | `(locale: string) => void` | **required** | Callback fired on locale change |
| `variant` | `'dropdown' \| 'flags' \| 'minimal'` | `'dropdown'` | Display variant |
| `className` | `string` | - | Custom CSS class |
| `showLabels` | `boolean` | `true` | Show locale labels |
| `position` | `'top' \| 'bottom'` | `'bottom'` | Dropdown position |
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| `currentLocale` | `string` | **required** | Current active locale code |
| `locales` | `LocaleOption[]` | **required** | Array of available locales |
| `onLocaleChange` | `(locale: string) => void` | **required** | Callback fired on locale change |
| `variant` | `'dropdown' \| 'flags' \| 'minimal'` | `'dropdown'` | Display variant |
| `className` | `string` | - | Custom CSS class |
| `showLabels` | `boolean` | `true` | Show locale labels |
| `position` | `'top' \| 'bottom'` | `'bottom'` | Dropdown position |
🧰 Tools
🪛 markdownlint-cli2 (0.20.0)

[warning] 99-99: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 99-99: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 99-99: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 99-99: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 99-99: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 99-99: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 99-99: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 99-99: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)

🤖 Prompt for AI Agents
In `@community/locale-switcher-widget/README.md` around lines 98 - 107, The
markdown table separator row between the header and body is missing spaces
around the pipe characters causing markdownlint MD060; update the separator row
(the line under the header that currently looks like
"|------|------|---------|-------------|") to include spaces around each pipe
(e.g. "| --- | --- | --- | --- |") so it matches the header row for the props
such as `currentLocale`, `locales`, `onLocaleChange`, `variant`, `className`,
`showLabels`, and `position`; ensure the separator columns align with the header
count and keep the same number of dashes per column.

Comment on lines 38 to 69
<button
onClick={() => setIsOpen(!isOpen)}
className="lingo-switcher-trigger"
aria-label="Select language"
aria-expanded={isOpen}
>
{currentOption.flag && <span className="lingo-flag">{currentOption.flag}</span>}
{showLabels && <span className="lingo-label">{currentOption.label}</span>}
<span className="lingo-arrow" aria-hidden="true">
{isOpen ? '▲' : '▼'}
</span>
</button>

{isOpen && (
<div
className={clsx('lingo-switcher-menu', `lingo-position-${position}`)}
role="menu"
>
{locales.map((locale) => (
<button
key={locale.code}
onClick={() => handleSelect(locale.code)}
className={clsx(
'lingo-switcher-option',
locale.code === currentLocale && 'lingo-active'
)}
role="menuitem"
>
{locale.flag && <span className="lingo-flag">{locale.flag}</span>}
{showLabels && <span className="lingo-label">{locale.label}</span>}
</button>
))}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Set button types to avoid accidental form submission.

Buttons default to type="submit". If this component is used inside a form, clicks can submit the form unintentionally.

🔧 Proposed fix
-      <button
+      <button
+        type="button"
         onClick={() => setIsOpen(!isOpen)}
         className="lingo-switcher-trigger"
         aria-label="Select language"
         aria-expanded={isOpen}
       >
...
-            <button
+            <button
+              type="button"
               key={locale.code}
               onClick={() => handleSelect(locale.code)}
               className={clsx(
                 'lingo-switcher-option',
                 locale.code === currentLocale && 'lingo-active'
               )}
               role="menuitem"
             >
🤖 Prompt for AI Agents
In `@community/locale-switcher-widget/src/components/DropdownSwitcher.tsx` around
lines 38 - 69, The buttons in DropdownSwitcher (the trigger button and each
locale option in the map) currently lack explicit types and will default to
type="submit" if placed inside a form; update the trigger button (the element
with class "lingo-switcher-trigger" that toggles isOpen) and the option buttons
inside the locales.map (class "lingo-switcher-option" that calls handleSelect)
to include type="button" so clicks do not submit enclosing forms.

Comment on lines 11 to 22
const currentIndex = locales.findIndex(l => l.code === currentLocale);
const nextLocale = locales[(currentIndex + 1) % locales.length];

return (
<button
onClick={() => onLocaleChange(nextLocale.code)}
className={clsx('lingo-switcher-minimal', className)}
aria-label={`Switch to ${nextLocale.label}`}
title={`Current: ${locales[currentIndex]?.label || currentLocale}`}
>
{nextLocale.flag && <span className="lingo-flag">{nextLocale.flag}</span>}
<span className="lingo-code">{nextLocale.code.toUpperCase()}</span>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard against empty locales to prevent runtime crashes.

If locales.length === 0, (currentIndex + 1) % locales.length yields NaN, and nextLocale becomes undefined; clicking will throw. Return null or a disabled button when no locales are provided.

🐛 Suggested fix
 export function MinimalSwitcher({
   currentLocale,
   locales,
   onLocaleChange,
   className
 }: LocaleSwitcherProps) {
+  if (locales.length === 0) {
+    return null;
+  }
   const currentIndex = locales.findIndex(l => l.code === currentLocale);
-  const nextLocale = locales[(currentIndex + 1) % locales.length];
+  const safeIndex = currentIndex >= 0 ? currentIndex : 0;
+  const nextLocale = locales[(safeIndex + 1) % locales.length];
🤖 Prompt for AI Agents
In `@community/locale-switcher-widget/src/components/MinimalSwitcher.tsx` around
lines 11 - 22, The component currently assumes locales is non-empty; guard by
checking locales.length and currentIndex before computing nextLocale in
MinimalSwitcher: if locales.length === 0 return null (or render a disabled
button), and handle currentIndex === -1 by defaulting to 0; ensure the code that
references nextLocale (onLocaleChange(nextLocale.code), nextLocale.flag,
nextLocale.code, nextLocale.label) only runs when nextLocale is defined to avoid
runtime crashes.

Lakshit-Gupta and others added 2 commits January 30, 2026 20:54
- Add package entry to changeset frontmatter
- Replace placeholder build scripts with actual vite/tsc commands
- Add type='button' to all buttons to prevent form submission
- Replace radio ARIA pattern with button group + aria-pressed
- Add empty locales array guard in MinimalSwitcher
- Add beforeEach mock cleanup in tests
- Fix markdown table separators and code block language hints
@github-actions
Copy link
Contributor

Thanks for your contribution! However, this PR needs to reference an issue that you're assigned to. Please find an unassigned issue to work on and include a reference like 'Closes #123' in your PR description, or get assigned to an existing issue first.

@github-actions github-actions bot closed this Jan 30, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @.vscode/settings.json:
- Around line 7-9: The added workspace setting "chat.tools.terminal.autoApprove"
with "pnpm": true looks unrelated and risky; remove the entire
"chat.tools.terminal.autoApprove" block from .vscode/settings.json so the PR
only contains locale-switcher-widget changes, or if this was intentional, keep
the key but set "pnpm": false and add a short rationale in the PR description
explaining why auto-approving pnpm is required and who approved it (so others
are aware); search for the JSON key "chat.tools.terminal.autoApprove" and the
"pnpm" value to locate and change the entry.

In `@community/locale-switcher-widget/package.json`:
- Around line 20-25: The package.json scripts block is missing a test entry so
unit tests under src/test/ can't be run; add a "test" script inside the existing
"scripts" object (alongside "dev", "build", "preview", "typecheck") that invokes
Vitest (e.g., "vitest" or "vitest run") so pnpm test and CI/Turborepo will
execute the unit tests; ensure the command matches your preferred Vitest flags
for watch vs CI mode.
- Around line 49-51: Update the `@types/react` dependency in package.json (the
"@types/react" entry) from the pinned "^18.3.18" to a range that includes React
19 (e.g., "^19.0.0") so type definitions match the peerDependency range; change
the version string in the dependencies/devDependencies where "@types/react" is
declared and run a lockfile install to update node_modules accordingly.

Comment on lines +7 to 9
"chat.tools.terminal.autoApprove": {
"pnpm": true
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unrelated change: auto-approve setting may be accidental.

This chat.tools.terminal.autoApprove setting appears unrelated to the locale-switcher-widget feature. It also introduces a security consideration by auto-approving pnpm commands in VS Code's chat terminal without user confirmation.

Was this change intentionally included in this PR? If not, consider reverting it. If it is intentional, please clarify the rationale, as it affects all developers using this workspace.

🤖 Prompt for AI Agents
In @.vscode/settings.json around lines 7 - 9, The added workspace setting
"chat.tools.terminal.autoApprove" with "pnpm": true looks unrelated and risky;
remove the entire "chat.tools.terminal.autoApprove" block from
.vscode/settings.json so the PR only contains locale-switcher-widget changes, or
if this was intentional, keep the key but set "pnpm": false and add a short
rationale in the PR description explaining why auto-approving pnpm is required
and who approved it (so others are aware); search for the JSON key
"chat.tools.terminal.autoApprove" and the "pnpm" value to locate and change the
entry.

Comment on lines +20 to +25
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"typecheck": "tsc --noEmit"
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Add a test script to run the unit tests.

The package includes test files under src/test/ with Vitest configured, but there's no test script defined. This prevents running tests via pnpm test and may cause the Turborepo pipeline to skip test validation for this package.

🧩 Proposed fix
   "scripts": {
     "dev": "vite",
     "build": "tsc && vite build",
     "preview": "vite preview",
-    "typecheck": "tsc --noEmit"
+    "typecheck": "tsc --noEmit",
+    "test": "vitest run",
+    "test:watch": "vitest"
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"typecheck": "tsc --noEmit"
},
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest"
},
🤖 Prompt for AI Agents
In `@community/locale-switcher-widget/package.json` around lines 20 - 25, The
package.json scripts block is missing a test entry so unit tests under src/test/
can't be run; add a "test" script inside the existing "scripts" object
(alongside "dev", "build", "preview", "typecheck") that invokes Vitest (e.g.,
"vitest" or "vitest run") so pnpm test and CI/Turborepo will execute the unit
tests; ensure the command matches your preferred Vitest flags for watch vs CI
mode.

Comment on lines +49 to +51
"@types/node": "^22.10.5",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

@types/react npm latest version available

💡 Result:

Latest @types/react version on npm: 19.2.9. (security.snyk.io)

Citations:


Update @types/react to support React 19.

The peer dependencies allow React 19 (^18.0.0 || ^19.0.0), but @types/react is pinned to ^18.3.18. Since @types/react v19 (currently 19.2.9) is available on npm, update the dependency to ^19.0.0 to ensure type definitions align with the supported React versions and prevent type mismatches for consumers using React 19.

🤖 Prompt for AI Agents
In `@community/locale-switcher-widget/package.json` around lines 49 - 51, Update
the `@types/react` dependency in package.json (the "@types/react" entry) from the
pinned "^18.3.18" to a range that includes React 19 (e.g., "^19.0.0") so type
definitions match the peerDependency range; change the version string in the
dependencies/devDependencies where "@types/react" is declared and run a lockfile
install to update node_modules accordingly.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant