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:
+5
-2
@@ -98,8 +98,9 @@ export const SettingsAdminWorkspaceContent = ({
|
||||
);
|
||||
},
|
||||
onError: (error) => {
|
||||
const errorMessage = error.message;
|
||||
enqueueErrorSnackBar({
|
||||
message: `Failed to impersonate user. ${error.message}`,
|
||||
message: t`Failed to impersonate user. ${errorMessage}`,
|
||||
});
|
||||
},
|
||||
}).finally(() => {
|
||||
@@ -128,8 +129,9 @@ export const SettingsAdminWorkspaceContent = ({
|
||||
if (isDefined(previousValue)) {
|
||||
updateFeatureFlagState(workspaceId, featureFlag, previousValue);
|
||||
}
|
||||
const errorMessage = error.message;
|
||||
enqueueErrorSnackBar({
|
||||
message: `Failed to update feature flag. ${error.message}`,
|
||||
message: t`Failed to update feature flag. ${errorMessage}`,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -146,6 +148,7 @@ export const SettingsAdminWorkspaceContent = ({
|
||||
value: (
|
||||
<Chip
|
||||
label={activeWorkspace?.name ?? ''}
|
||||
emptyLabel={t`Untitled`}
|
||||
leftComponent={
|
||||
<AvatarChip
|
||||
avatarUrl={
|
||||
|
||||
+4
-3
@@ -5,6 +5,7 @@ import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type ConfigVariableValue } from 'twenty-shared/types';
|
||||
import { CustomError } from 'twenty-shared/utils';
|
||||
import { MenuItemMultiSelect } from 'twenty-ui/navigation';
|
||||
@@ -109,7 +110,7 @@ export const ConfigVariableDatabaseInput = ({
|
||||
label:
|
||||
Array.isArray(value) && value.length > 0
|
||||
? value.join(', ')
|
||||
: 'Select options',
|
||||
: t`Select options`,
|
||||
}}
|
||||
isDisabled={disabled}
|
||||
hasRightElement={false}
|
||||
@@ -152,7 +153,7 @@ export const ConfigVariableDatabaseInput = ({
|
||||
}
|
||||
}}
|
||||
disabled={disabled}
|
||||
placeholder={placeholder || 'Enter JSON array'}
|
||||
placeholder={placeholder || t`Enter JSON array`}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
@@ -184,7 +185,7 @@ export const ConfigVariableDatabaseInput = ({
|
||||
}
|
||||
onChange={(text) => onChange(text)}
|
||||
disabled={disabled}
|
||||
placeholder={placeholder || 'Enter value'}
|
||||
placeholder={placeholder || t`Enter value`}
|
||||
fullWidth
|
||||
/>
|
||||
);
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ export const ConfigVariableValueInput = ({
|
||||
options={variable.options}
|
||||
disabled={disabled}
|
||||
placeholder={
|
||||
disabled ? 'Undefined' : t`Enter a value to store in database`
|
||||
disabled ? t`Undefined` : t`Enter a value to store in database`
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ export const SettingsAdminConfigVariables = () => {
|
||||
|
||||
const groupOptions = useMemo(
|
||||
() => [
|
||||
{ value: 'all', label: 'All Groups' },
|
||||
{ value: 'all', label: t`All Groups` },
|
||||
...allGroups.map((group) => ({
|
||||
value: group.name,
|
||||
label: group.name,
|
||||
|
||||
+3
-2
@@ -1,3 +1,4 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { SettingsAdminConfigVariablesRow } from '@/settings/admin-panel/config-variables/components/SettingsAdminConfigVariablesRow';
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import { TableBody } from '@/ui/layout/table/components/TableBody';
|
||||
@@ -20,8 +21,8 @@ export const SettingsAdminConfigVariablesTable = ({
|
||||
return (
|
||||
<Table>
|
||||
<TableRow gridAutoColumns="5fr 3fr 1fr">
|
||||
<TableHeader>Name</TableHeader>
|
||||
<TableHeader align="right">Value</TableHeader>
|
||||
<TableHeader>{t`Name`}</TableHeader>
|
||||
<TableHeader align="right">{t`Value`}</TableHeader>
|
||||
<TableHeader align="right"></TableHeader>
|
||||
</TableRow>
|
||||
<StyledTableBody>
|
||||
|
||||
+7
-4
@@ -1,5 +1,6 @@
|
||||
import { SettingsAdminTableCard } from '@/settings/admin-panel/components/SettingsAdminTableCard';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { H2Title } from 'twenty-ui/display';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
|
||||
@@ -17,25 +18,27 @@ export const SettingsAdminHealthAccountSyncCountersTable = ({
|
||||
title: string;
|
||||
description: string;
|
||||
}) => {
|
||||
const { t } = useLingui();
|
||||
|
||||
if (!details) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const items = [
|
||||
{
|
||||
label: 'Active Sync',
|
||||
label: t`Active Sync`,
|
||||
value: details.counters.ACTIVE,
|
||||
},
|
||||
{
|
||||
label: 'Total Jobs',
|
||||
label: t`Total Jobs`,
|
||||
value: details.totalJobs,
|
||||
},
|
||||
{
|
||||
label: 'Failed Jobs',
|
||||
label: t`Failed Jobs`,
|
||||
value: details.failedJobs,
|
||||
},
|
||||
{
|
||||
label: 'Failure Rate',
|
||||
label: t`Failure Rate`,
|
||||
value: `${details.failureRate}%`,
|
||||
},
|
||||
];
|
||||
|
||||
+3
-2
@@ -1,3 +1,4 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { Status } from 'twenty-ui/display';
|
||||
import { AdminPanelHealthServiceStatus } from '~/generated-metadata/graphql';
|
||||
|
||||
@@ -9,10 +10,10 @@ export const SettingsAdminHealthStatusRightContainer = ({
|
||||
return (
|
||||
<>
|
||||
{status === AdminPanelHealthServiceStatus.OPERATIONAL && (
|
||||
<Status color="green" text="Operational" weight="medium" />
|
||||
<Status color="green" text={t`Operational`} weight="medium" />
|
||||
)}
|
||||
{status === AdminPanelHealthServiceStatus.OUTAGE && (
|
||||
<Status color="red" text="Outage" weight="medium" />
|
||||
<Status color="red" text={t`Outage`} weight="medium" />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
+3
-1
@@ -38,12 +38,14 @@ export const SettingsAdminJsonDataIndicatorHealthStatus = () => {
|
||||
|
||||
const isAnyNode = () => true;
|
||||
|
||||
const serviceLabel = indicatorHealth.label;
|
||||
|
||||
return (
|
||||
<Section>
|
||||
{isDown && (
|
||||
<StyledErrorMessage>
|
||||
{indicatorHealth.errorMessage ||
|
||||
`${indicatorHealth.label} service is unreachable`}
|
||||
t`${serviceLabel} service is unreachable`}
|
||||
</StyledErrorMessage>
|
||||
)}
|
||||
{parsedDetails && (
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ export const SettingsAdminQueueJobRowDropdownMenu = ({
|
||||
dropdownPlacement="right-start"
|
||||
clickableComponent={
|
||||
<LightIconButton
|
||||
aria-label="Job Actions"
|
||||
aria-label={t`Job Actions`}
|
||||
Icon={IconDotsVertical}
|
||||
accent="tertiary"
|
||||
/>
|
||||
|
||||
+2
-1
@@ -53,8 +53,9 @@ export const SettingsAdminWorkerMetricsGraph = ({
|
||||
},
|
||||
fetchPolicy: 'no-cache',
|
||||
onError: (error) => {
|
||||
const errorMessage = error.message;
|
||||
enqueueErrorSnackBar({
|
||||
message: `Error fetching worker metrics: ${error.message}`,
|
||||
message: t`Error fetching worker metrics: ${errorMessage}`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user