feat: add lingui/no-unlocalized-strings ESLint rule and fix translations (#16610)

## Summary
This PR adds the `lingui/no-unlocalized-strings` ESLint rule to detect
untranslated strings and fixes translation issues across multiple
components.

## Changes

### ESLint Configuration (`eslint.config.react.mjs`)
- Added comprehensive `ignore` patterns for non-translatable strings
(CSS values, HTML attributes, technical identifiers)
- Added `ignoreNames` for props that don't need translation (className,
data-*, aria-*, etc.)
- Added `ignoreFunctions` for console methods, URL APIs, and other
non-user-facing functions
- Disabled rule for debug files, storybook, and test files

### Components Fixed (~19 files)
- Object record components (field inputs, pickers, merge dialogs)
- Settings components (accounts, admin panel)
- Serverless function components
- Record table and title cell components

## Status
🚧 **Work in Progress** - ~124 files remaining to fix

This PR is being submitted as draft to allow progressive fixing of
remaining translation issues.

## Testing
- Run `npx eslint "src/**/*.tsx"` in `packages/twenty-front` to check
remaining issues
This commit is contained in:
Félix Malfait
2025-12-17 22:08:33 +01:00
committed by GitHub
parent c13b955a36
commit 1088f7bbab
368 changed files with 56823 additions and 836 deletions
@@ -24,6 +24,7 @@ export type MultipleAvatarChipProps = {
forceEmptyText?: boolean;
variant?: ChipVariant;
rightComponent?: React.ReactNode;
emptyLabel?: string;
};
export const MultipleAvatarChip = ({
@@ -35,6 +36,7 @@ export const MultipleAvatarChip = ({
rightComponent,
variant = ChipVariant.Static,
forceEmptyText = false,
emptyLabel,
}: MultipleAvatarChipProps) => {
return (
<StyledChipContainer onClick={onClick} data-testid={testId}>
@@ -53,6 +55,7 @@ export const MultipleAvatarChip = ({
rightComponent={rightComponent}
clickable={isDefined(onClick)}
maxWidth={maxWidth}
emptyLabel={emptyLabel}
/>
</StyledChipContainer>
);
@@ -35,6 +35,7 @@ export type ChipProps = {
rightComponent?: (() => ReactNode) | ReactNode | null;
className?: string;
forceEmptyText?: boolean;
emptyLabel?: string;
};
const StyledDiv = withTheme(styled.div<{ theme: Theme }>`
@@ -152,6 +153,7 @@ export const Chip = ({
className,
maxWidth,
forceEmptyText = false,
emptyLabel = 'Untitled',
}: ChipProps) => {
return (
<StyledContainer
@@ -168,7 +170,7 @@ export const Chip = ({
{!isLabelHidden && label && label.trim() ? (
<OverflowingTextWithTooltip size={size} text={label} />
) : !forceEmptyText && !isLabelHidden ? (
<StyledDiv>Untitled</StyledDiv>
<StyledDiv>{emptyLabel}</StyledDiv>
) : (
''
)}
@@ -42,6 +42,7 @@ export const LinkChip = ({
onClick,
triggerEvent,
target,
emptyLabel,
}: LinkChipProps) => {
const { onClick: onClickHandler, onMouseDown: onMouseDownHandler } =
useMouseDownNavigation({
@@ -73,6 +74,7 @@ export const LinkChip = ({
accent={accent}
className={className}
maxWidth={maxWidth}
emptyLabel={emptyLabel}
/>
</StyledLink>
);