Skip to content

Commit f0fb00c

Browse files
committed
feat(no-unlocalized-strings): support camelCase styling variable names
- colorClasses, buttonStyles, statusColors, etc. now auto-ignored - Matches plural suffixes: Classes, Colors, Styles, Icons, Images, Sizes, Ids
1 parent 9730283 commit f0fb00c

File tree

4 files changed

+53
-8
lines changed

4 files changed

+53
-8
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const status: Status = "loading" // String literal union
2626
<Box containerClassName="flex items-center" /> // *ClassName, *Color, *Style, etc.
2727
<div className={clsx("px-4", "py-2")} /> // className utilities (clsx, cn, etc.)
2828
<Calendar classNames={{ day: "bg-white" }} /> // nested classNames objects
29-
const STATUS_COLORS = { active: "bg-green-100" } // *_COLORS, *_CLASSES, etc.
29+
const colorClasses = { active: "bg-green-100" } // *Classes, *Colors, *Styles, etc.
3030
const price = "1,00€" // No letters = technical
3131

3232
// ❌ Reported - actual user-visible text
@@ -56,7 +56,7 @@ const label = t("save") // ❌ Not confused with Lingui
5656
- 🎯 Detects missing localization of user-visible text
5757
- 🧠 Zero-config recognition of technical strings via TypeScript types
5858
- 🎨 Auto-ignores styling props (`*ClassName`, `*Color`, `*Style`, `*Icon`, `*Image`, `*Size`, `*Id`)
59-
- 📦 Auto-ignores styling constants (`STATUS_COLORS`, `BUTTON_CLASSES`, `THEME_STYLES`, etc.)
59+
- 📦 Auto-ignores styling variables (`colorClasses`, `STATUS_COLORS`, `buttonStyles`, etc.)
6060
- 🔢 Auto-ignores numeric/symbolic strings without letters (`"1,00€"`, `"12:30"`)
6161
- 🔒 Verifies Lingui macros actually come from `@lingui/*` packages (no false positives from similarly-named functions)
6262

docs/rules/no-unlocalized-strings.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,36 @@ This covers common patterns in component libraries like Chakra UI, Material UI,
195195

196196
**Note**: Strings inside callback functions (like `onClick`) are NOT ignored, even when `className` is present on the same element.
197197

198-
#### Auto-Detected Styling Constants
198+
#### Auto-Detected Styling Variables
199199

200-
UPPER_CASE constant names with styling-related suffixes are also automatically ignored:
200+
Variable names (both UPPER_CASE and camelCase) with styling-related suffixes are automatically ignored:
201+
202+
**camelCase variables** (for object mappings):
203+
204+
| Suffix | Examples |
205+
|--------|----------|
206+
| `Classes`, `ClassName`, `ClassNames` | `colorClasses`, `buttonClassNames` |
207+
| `Colors` | `statusColors`, `themeColors` |
208+
| `Styles` | `buttonStyles`, `cardStyles` |
209+
| `Icons` | `navIcons`, `statusIcons` |
210+
| `Images` | `heroImages`, `avatarImages` |
211+
| `Sizes` | `iconSizes`, `fontSizes` |
212+
| `Ids` | `elementIds`, `sectionIds` |
213+
214+
```tsx
215+
// camelCase variables with styling suffixes
216+
const colorClasses = {
217+
Solar: "bg-orange-100 text-orange-800",
218+
Wind: "bg-blue-100 text-blue-800",
219+
}
220+
221+
const buttonStyles = {
222+
primary: "px-4 py-2 bg-blue-500",
223+
secondary: "px-4 py-2 bg-gray-200",
224+
}
225+
```
226+
227+
**UPPER_CASE constants**:
201228

202229
| Suffix | Examples |
203230
|--------|----------|

src/rules/no-unlocalized-strings.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,20 @@ ruleTester.run("no-unlocalized-strings", noUnlocalizedStrings, {
165165
{ code: 'const AVATAR_SIZES = { sm: "w-8 h-8", lg: "w-16 h-16" }', filename: "test.tsx" },
166166
{ code: 'const CARD_IMAGES = { hero: "/images/hero.jpg" }', filename: "test.tsx" },
167167
{ code: 'const ELEMENT_IDS = { header: "main-header", footer: "main-footer" }', filename: "test.tsx" },
168-
// Singular forms
168+
// Singular forms (UPPER_CASE)
169169
{ code: 'const DEFAULT_COLOR = { value: "#ff0000" }', filename: "test.tsx" },
170170
{ code: 'const MAIN_CLASS = { container: "mx-auto max-w-7xl" }', filename: "test.tsx" },
171+
// camelCase styling variables
172+
{
173+
code: 'const colorClasses = { Solar: "bg-orange-100 text-orange-800", Wind: "bg-blue-100" }',
174+
filename: "test.tsx"
175+
},
176+
{
177+
code: 'const buttonStyles = { primary: "px-4 py-2 bg-blue-500", secondary: "px-4 py-2 bg-gray-200" }',
178+
filename: "test.tsx"
179+
},
180+
{ code: 'const statusColors = { active: "#00ff00", inactive: "#cccccc" }', filename: "test.tsx" },
181+
{ code: 'const iconSizes = { sm: "w-4 h-4", lg: "w-8 h-8" }', filename: "test.tsx" },
171182
// Nested objects should NOT be ignored (only direct property values)
172183
// These are in the invalid section below
173184

src/rules/no-unlocalized-strings.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,11 @@ function isStylingProperty(propertyName: string): boolean {
515515
const UPPER_CASE_STYLING_PATTERN =
516516
/^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*_(CLASSNAMES?|CLASSES?|CLASS|COLORS?|STYLES?|ICONS?|IMAGES?|SIZES?|IDS?)$/
517517

518+
/** camelCase variable names with styling-related suffixes (plural forms for objects) */
519+
const CAMEL_CASE_STYLING_VAR_PATTERN = /^[a-z][a-zA-Z]*(Classes|ClassNames?|Colors|Styles|Icons|Images|Sizes|Ids)$/
520+
518521
/**
519-
* Checks if a variable name is a styling/technical constant.
522+
* Checks if a variable name is a styling/technical constant or variable.
520523
*
521524
* Matches UPPER_CASE constants ending with:
522525
* - "_CLASS", "_CLASSES", "_CLASSNAME", "_CLASSNAMES"
@@ -527,10 +530,14 @@ const UPPER_CASE_STYLING_PATTERN =
527530
* - "_SIZE", "_SIZES"
528531
* - "_ID", "_IDS"
529532
*
530-
* Examples: STATUS_COLORS, BUTTON_CLASSES, THEME_STYLES
533+
* Also matches camelCase variables ending with:
534+
* - "Classes", "ClassName", "ClassNames"
535+
* - "Colors", "Styles", "Icons", "Images", "Sizes", "Ids"
536+
*
537+
* Examples: STATUS_COLORS, BUTTON_CLASSES, colorClasses, buttonStyles
531538
*/
532539
function isStylingConstant(variableName: string): boolean {
533-
return UPPER_CASE_STYLING_PATTERN.test(variableName)
540+
return UPPER_CASE_STYLING_PATTERN.test(variableName) || CAMEL_CASE_STYLING_VAR_PATTERN.test(variableName)
534541
}
535542

536543
/**

0 commit comments

Comments
 (0)