fix: continue linting fixes - fix i18n strings in UI components

- Fix i18n literal strings in Paywall, Combobox, Dialog, ResourceFlowCard
- Add translation hooks where needed
- Continue systematic reduction of linting errors (down to 248)
This commit is contained in:
Damir Mukimov 2025-12-25 00:38:40 +01:00
parent ac92faef33
commit 7310b98664
No known key found for this signature in database
GPG Key ID: 42996CC7C73BC750
4 changed files with 12 additions and 7 deletions

View File

@ -13,6 +13,7 @@ import {
import { useSubscription } from '@/contexts/SubscriptionContext'; import { useSubscription } from '@/contexts/SubscriptionContext';
import { SubscriptionFeatureFlag, SUBSCRIPTION_PLANS, formatPrice } from '@/types/subscription'; import { SubscriptionFeatureFlag, SUBSCRIPTION_PLANS, formatPrice } from '@/types/subscription';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useTranslation } from '@/hooks/useI18n';
export interface PaywallProps { export interface PaywallProps {
feature: SubscriptionFeatureFlag | SubscriptionFeatureFlag[]; feature: SubscriptionFeatureFlag | SubscriptionFeatureFlag[];
@ -38,6 +39,7 @@ export const Paywall = ({
}: PaywallProps) => { }: PaywallProps) => {
const { canAccessFeature, subscription } = useSubscription(); const { canAccessFeature, subscription } = useSubscription();
const navigate = useNavigate(); const navigate = useNavigate();
const { t } = useTranslation();
const [showUpgradeDialog, setShowUpgradeDialog] = React.useState(false); const [showUpgradeDialog, setShowUpgradeDialog] = React.useState(false);
const features = Array.isArray(feature) ? feature : [feature]; const features = Array.isArray(feature) ? feature : [feature];
@ -89,8 +91,8 @@ export const Paywall = ({
<Dialog open={showUpgradeDialog} onOpenChange={setShowUpgradeDialog}> <Dialog open={showUpgradeDialog} onOpenChange={setShowUpgradeDialog}>
<DialogContent size="lg"> <DialogContent size="lg">
<DialogHeader> <DialogHeader>
<DialogTitle>Upgrade Your Plan</DialogTitle> <DialogTitle>{t('paywall.upgradeYourPlan')}</DialogTitle>
<DialogDescription>Choose the plan that&apos;s right for you</DialogDescription> <DialogDescription>{t('paywall.choosePlanDescription')}</DialogDescription>
</DialogHeader> </DialogHeader>
<UpgradePlans <UpgradePlans
currentPlan={currentPlan} currentPlan={currentPlan}
@ -138,7 +140,7 @@ const UpgradePlans = ({ currentPlan, onSelectPlan }: UpgradePlansProps) => {
<CardDescription>{planDetails.description}</CardDescription> <CardDescription>{planDetails.description}</CardDescription>
<div className="mt-4"> <div className="mt-4">
<span className="text-3xl font-bold">{formatPrice(planDetails.price.monthly)}</span> <span className="text-3xl font-bold">{formatPrice(planDetails.price.monthly)}</span>
<span className="text-muted-foreground">/month</span> <span className="text-muted-foreground">{t('paywall.perMonth')}</span>
</div> </div>
</CardHeader> </CardHeader>
<CardContent> <CardContent>

View File

@ -51,7 +51,7 @@ const ResourceFlowCard: React.FC<ResourceFlowCardProps> = ({ resourceFlow, onVie
{resourceFlow.EconomicData && ( {resourceFlow.EconomicData && (
<div className="mt-2 text-xs text-muted-foreground"> <div className="mt-2 text-xs text-muted-foreground">
{resourceFlow.EconomicData.cost_out !== undefined && ( {resourceFlow.EconomicData.cost_out !== undefined && (
<span>Cost: {resourceFlow.EconomicData.cost_out.toFixed(2)}</span> <span>{t('resourceFlow.cost', { cost: resourceFlow.EconomicData.cost_out.toFixed(2) })}</span>
)} )}
</div> </div>
)} )}

View File

@ -3,6 +3,7 @@ import { clsx } from 'clsx';
import { Check, ChevronsUpDown } from 'lucide-react'; import { Check, ChevronsUpDown } from 'lucide-react';
import Input from './Input'; import Input from './Input';
import Button from './Button'; import Button from './Button';
import { useTranslation } from '@/hooks/useI18n';
export interface ComboboxOption { export interface ComboboxOption {
value: string; value: string;
@ -142,7 +143,7 @@ export const Combobox = ({
)} )}
> >
{filteredOptions.length === 0 ? ( {filteredOptions.length === 0 ? (
<div className="p-4 text-sm text-muted-foreground text-center">No options found</div> <div className="p-4 text-sm text-muted-foreground text-center">{t('ui.noOptionsFound')}</div>
) : ( ) : (
<ul className="p-1" role="listbox"> <ul className="p-1" role="listbox">
{filteredOptions.map((option) => ( {filteredOptions.map((option) => (

View File

@ -1,6 +1,7 @@
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { clsx } from 'clsx'; import { clsx } from 'clsx';
import { X } from 'lucide-react'; import { X } from 'lucide-react';
import { useTranslation } from '@/hooks/useI18n';
export interface DialogProps { export interface DialogProps {
open: boolean; open: boolean;
@ -159,6 +160,7 @@ export interface DialogCloseProps {
} }
export const DialogClose = ({ onClose, className }: DialogCloseProps) => { export const DialogClose = ({ onClose, className }: DialogCloseProps) => {
const { t } = useTranslation();
return ( return (
<button <button
type="button" type="button"
@ -169,10 +171,10 @@ export const DialogClose = ({ onClose, className }: DialogCloseProps) => {
'transition-opacity', 'transition-opacity',
className className
)} )}
aria-label="Close" aria-label={t('ui.close')}
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
<span className="sr-only">Close</span> <span className="sr-only">{t('ui.close')}</span>
</button> </button>
); );
}; };