Merge pull request #14 from RooCodeInc/cte/clean-up-i18n

This commit is contained in:
Chris Estreich 2025-05-15 21:18:12 -07:00 committed by GitHub
commit 81d3e375bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 133 additions and 355 deletions

View file

@ -0,0 +1,87 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
// npx tsx scripts/find-missing-translations.ts
import fs from 'fs';
import path from 'path';
function extractKeys(obj: any, prefix = ''): string[] {
let keys: string[] = [];
for (const key in obj) {
const currentKey = prefix ? `${prefix}.${key}` : key;
if (typeof obj[key] === 'object' && obj[key] !== null) {
keys = [...keys, ...extractKeys(obj[key], currentKey)];
} else {
keys.push(currentKey);
}
}
return keys;
}
async function main() {
const rootDir = path.resolve(__dirname, '..');
const localesDir = path.join('src', 'i18n', 'locales');
const files = fs
.readdirSync(path.join(rootDir, localesDir))
.filter((file) => file.endsWith('.json'))
.map((file) => path.join(rootDir, localesDir, file));
const localeKeys: { [locale: string]: Set<string> } = {};
const allKeys = new Set<string>();
for (const file of files) {
const keys = extractKeys(JSON.parse(fs.readFileSync(file, 'utf8')));
const relativePath = path.join(localesDir, path.basename(file));
localeKeys[relativePath] = new Set(keys);
for (const key of keys) {
allKeys.add(key);
}
}
Object.entries(localeKeys).forEach(([locale, keys]) => {
const missingKeys = Array.from(allKeys).filter((key) => !keys.has(key));
if (missingKeys.length > 0) {
console.log(
`\n[${locale}] Missing ${missingKeys.length} translation(s):`,
);
const groupedMissing = new Map<string, string[]>();
for (const key of missingKeys) {
const parts = key.split('.');
if (parts.length >= 2) {
const namespace = parts[0];
const subKey = parts.slice(1).join('.');
if (namespace && subKey) {
if (!groupedMissing.has(namespace)) {
groupedMissing.set(namespace, []);
}
const group = groupedMissing.get(namespace);
if (group) {
group.push(subKey);
}
}
}
}
for (const [namespace, keys] of groupedMissing.entries()) {
console.log(`${namespace}`);
keys.forEach((key) => console.log(`\t${key}`));
}
} else {
console.log(`\n[${locale}] No missing translations`);
}
});
}
main();

View file

@ -1,6 +1,6 @@
'use server';
import type { Locale } from '@/lib/locale';
import type { Locale } from '@/i18n/locale';
import { cookies } from 'next/headers';
export const setLocale = async (locale: Locale) => {

View file

@ -1,13 +1,5 @@
import { getLocale, getTranslations } from 'next-intl/server';
import { DashboardHeader } from '@/components/dashboard/DashboardHeader';
export async function generateMetadata() {
const locale = await getLocale();
const t = await getTranslations({ locale, namespace: 'Dashboard' });
return { title: t('meta_title'), description: t('meta_description') };
}
export default function DashboardLayout({
children,
}: {

View file

@ -5,7 +5,7 @@ import { NextIntlClientProvider } from 'next-intl';
import { getLocale, getTranslations, setRequestLocale } from 'next-intl/server';
import { ClerkProvider } from '@clerk/nextjs';
import { getClerkLocale } from '@/lib/locale';
import { getClerkLocale } from '@/i18n/locale';
import { ThemeProvider } from '@/components/layout';
import { ToastProvider, ToastViewport } from '@/components/ui/toast';
import { ToastProvider as ToastContextProvider } from '@/components/ui/toast-context';

View file

@ -1,13 +1,5 @@
import { getLocale, getTranslations } from 'next-intl/server';
import { CreateOrg } from './CreateOrg';
export async function generateMetadata() {
const locale = await getLocale();
const t = await getTranslations({ locale, namespace: 'Dashboard' });
return { title: t('meta_title'), description: t('meta_description') };
}
export const dynamic = 'force-dynamic';
export default async function Page() {

View file

@ -1,13 +1,5 @@
import { getLocale, getTranslations } from 'next-intl/server';
import { SelectOrg } from './SelectOrg';
export async function generateMetadata() {
const locale = await getLocale();
const t = await getTranslations({ locale, namespace: 'Dashboard' });
return { title: t('meta_title'), description: t('meta_description') };
}
export const dynamic = 'force-dynamic';
export default async function Page() {

View file

@ -1,6 +1,6 @@
import type { MetadataRoute } from 'next';
import { getBaseUrl } from '@/lib/getBaseUrl';
import { getBaseUrl } from '@/lib/metadata';
export default function robots(): MetadataRoute.Robots {
return {

View file

@ -1,13 +1,5 @@
import { getLocale, getTranslations } from 'next-intl/server';
import { SignIn } from './SignIn';
export async function generateMetadata() {
const locale = await getLocale();
const t = await getTranslations({ locale, namespace: 'SignIn' });
return { title: t('meta_title'), description: t('meta_description') };
}
export default function Page() {
return <SignIn />;
}

View file

@ -1,13 +1,5 @@
import { getLocale, getTranslations } from 'next-intl/server';
import { SignUp } from './SignUp';
export async function generateMetadata() {
const locale = await getLocale();
const t = await getTranslations({ locale, namespace: 'SignUp' });
return { title: t('meta_title'), description: t('meta_description') };
}
export default function Page() {
return <SignUp />;
}

View file

@ -1,6 +1,6 @@
import type { MetadataRoute } from 'next';
import { getBaseUrl } from '@/lib/getBaseUrl';
import { getBaseUrl } from '@/lib/metadata';
export default function sitemap(): MetadataRoute.Sitemap {
return [

View file

@ -20,7 +20,6 @@ import { Input } from '@/components/ui/input';
import { Slider } from '@/components/ui/slider';
import { useToast } from '@/components/ui/toast-context';
// Default parameters form type
type DefaultParamsFormValues = {
experimentalPowerSteering: boolean;
terminalOutputLimit: number;
@ -52,7 +51,6 @@ const DefaultParametersPage = () => {
const [isSaving, setIsSaving] = useState(false);
// Form for default parameters
const form = useForm<DefaultParamsFormValues>({
defaultValues: {
experimentalPowerSteering: true,

View file

@ -1,10 +1,10 @@
'use client';
import React, { useMemo, useState } from 'react';
import Link from 'next/link';
import { useTranslations } from 'next-intl';
import React, { useMemo, useState } from 'react';
import { Button } from '@/components/ui/button';
import { Button } from '@/components/ui';
type TimePeriod = '7' | '30' | '90';
@ -20,9 +20,7 @@ export const UsageAnalyticsCard = () => {
const t = useTranslations('DashboardIndex');
const [timePeriod, setTimePeriod] = useState<TimePeriod>('7');
// Mock data based on selected time period
const analyticsData = useMemo<AnalyticsData>(() => {
// Return different data based on timePeriod
switch (timePeriod) {
case '7':
return {
@ -59,8 +57,6 @@ export const UsageAnalyticsCard = () => {
{t('analytics_description')}
</p>
</div>
{/* Time period toggle */}
<div className="mb-4 flex space-x-2">
<Button
variant={timePeriod === '7' ? 'default' : 'outline'}
@ -84,10 +80,7 @@ export const UsageAnalyticsCard = () => {
{t('analytics_period_90_days')}
</Button>
</div>
{/* Metrics grid */}
<div className="grid grid-cols-2 gap-4 md:grid-cols-5">
{/* Active Developers */}
<div className="rounded-lg bg-background p-3">
<div className="text-xs text-muted-foreground">
{t('analytics_active_developers')}
@ -96,8 +89,6 @@ export const UsageAnalyticsCard = () => {
{analyticsData.activeDevelopers}
</div>
</div>
{/* Tasks Started */}
<div className="rounded-lg bg-background p-3">
<div className="text-xs text-muted-foreground">
{t('analytics_tasks_started')}
@ -106,8 +97,6 @@ export const UsageAnalyticsCard = () => {
{analyticsData.tasksStarted}
</div>
</div>
{/* Tasks Completed */}
<div className="rounded-lg bg-background p-3">
<div className="text-xs text-muted-foreground">
{t('analytics_tasks_completed')}
@ -116,8 +105,6 @@ export const UsageAnalyticsCard = () => {
{analyticsData.tasksCompleted}
</div>
</div>
{/* Tokens Consumed */}
<div className="rounded-lg bg-background p-3">
<div className="text-xs text-muted-foreground">
{t('analytics_tokens_consumed')}
@ -126,8 +113,6 @@ export const UsageAnalyticsCard = () => {
{analyticsData.tokensConsumed}
</div>
</div>
{/* LLM Model Costs */}
<div className="rounded-lg bg-background p-3">
<div className="text-xs text-muted-foreground">
{t('analytics_llm_costs')}
@ -137,8 +122,6 @@ export const UsageAnalyticsCard = () => {
</div>
</div>
</div>
{/* Link to detailed analytics */}
<div className="mt-4 text-right">
<Link
href="/dashboard/analytics"

View file

@ -4,7 +4,7 @@ import { useCallback } from 'react';
import { useRouter } from 'next/navigation';
import { useLocale } from 'next-intl';
import { Locales, isLocale } from '@/lib/locale';
import { Locales, isLocale } from '@/i18n/locale';
import { setLocale } from '@/actions/locale';
import {
Button,

View file

@ -1,105 +1,24 @@
{
"Index": {
"meta_title": "SaaS Template - The perfect SaaS template to build and scale your business with ease.",
"meta_description": "A free and open-source landing page template for your SaaS business, built with React, TypeScript, Shadcn UI, and Tailwind CSS."
"meta_title": "Roo Code Cloud",
"meta_description": "Cloud management for Roo Code."
},
"Navbar": {
"sign_in": "Sign In",
"sign_up": "Sign Up",
"product": "Product",
"docs": "Docs",
"blog": "Blog",
"community": "Community",
"company": "Company"
},
"Hero": {
"follow_twitter": "Follow @Ixartz on Twitter",
"title": "The perfect <important>SaaS template</important> to build and scale your business with ease.",
"description": "A free and open-source landing page template for your SaaS business, built with React, TypeScript, Shadcn UI, and Tailwind CSS.",
"primary_button": "Get Started",
"secondary_button": "Star on GitHub"
},
"Sponsors": {
"title": "Sponsored by"
},
"Features": {
"section_subtitle": "Features",
"section_title": "Unlock the Full Potential of the SaaS Template",
"section_description": "A free and open-source landing page template for your SaaS business, built with React, TypeScript, Shadcn UI, and Tailwind CSS.",
"feature1_title": "Node.js",
"feature2_title": "React",
"feature3_title": "Tailwind CSS",
"feature4_title": "TypeScript",
"feature5_title": "Shadcn UI",
"feature6_title": "ESLint",
"feature_description": "A free and open-source landing page template for your SaaS business, built with React, TypeScript, Shadcn UI, and Tailwind CSS."
},
"Pricing": {
"section_subtitle": "Features",
"section_title": "Unlock the Full Potential of the SaaS Template",
"section_description": "A free and open-source landing page template for your SaaS business, built with React, TypeScript, Shadcn UI, and Tailwind CSS.",
"button_text": "Get Started"
},
"PricingPlan": {
"free_plan_name": "Free",
"premium_plan_name": "Premium",
"enterprise_plan_name": "Enterprise",
"free_plan_description": "For individuals",
"premium_plan_description": "For small teams",
"enterprise_plan_description": "For industry leaders",
"feature_team_member": "{number} Team Members",
"feature_website": "{number} Websites",
"feature_storage": "{number} GB Storage",
"feature_transfer": "{number} TB Transfer",
"feature_email_support": "Email Support",
"plan_interval_month": "month",
"plan_interval_year": "year",
"next_renew_date": "Your subscription renews on {date}"
},
"FAQ": {
"question": "Lorem ipsum dolor sit amet, consectetur adipiscing elit?",
"answer": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam aliquam enim dui, id consequat turpis ullamcorper ac. Mauris id quam dolor. Nullam eu egestas turpis. Proin risus elit, sollicitudin in mi a, accumsan euismod turpis. In euismod mi sed diam tristique hendrerit."
},
"CTA": {
"title": "You are ready?",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
"button_text": "Star on GitHub"
"sign_up": "Sign Up"
},
"Footer": {
"product": "Product",
"docs": "Docs",
"blog": "Blog",
"community": "Community",
"company": "Company",
"terms_of_service": "Terms Of Service",
"privacy_policy": "Privacy Policy",
"designed_by": "Designed by <author></author>."
},
"ProtectFallback": {
"not_enough_permission": "You do not have the permissions to perform this action"
},
"SignIn": {
"meta_title": "Sign in",
"meta_description": "Seamlessly sign in to your account with our user-friendly login process."
},
"SignUp": {
"meta_title": "Sign up",
"meta_description": "Effortlessly create an account through our intuitive sign-up process."
"privacy_policy": "Privacy Policy"
},
"DashboardLayout": {
"home": "Home",
"analytics": "Analytics",
"todos": "Todos",
"members": "Members",
"audit_logs": "Audit Logs",
"billing": "Billing",
"settings": "Settings",
"provider_whitelist": "Provider Whitelist"
},
"Dashboard": {
"meta_title": "SaaS Template Dashboard",
"meta_description": "A free and open-source landing page template for your SaaS business, built with Next.js, TypeScript, Shadcn UI, and Tailwind CSS."
},
"DashboardIndex": {
"title_bar": "Dashboard",
"title_bar_description": "Welcome to your dashboard",
@ -138,56 +57,6 @@
"parameters_section_title": "Default Parameters",
"parameters_section_description": "Set global default parameters for AI model calls"
},
"Billing": {
"title_bar": "Billing",
"title_bar_description": "Manage your billing and subscription",
"current_section_title": "Current Plan",
"current_section_description": "Adjust your payment plan to best suit your requirements",
"manage_subscription_button": "Manage Subscription"
},
"BillingOptions": {
"current_plan": "Current Plan",
"upgrade_plan": "Get Started"
},
"CheckoutConfirmation": {
"title_bar": "Payment Confirmation",
"message_state_title": "Payment successful",
"message_state_description": "Your payment has been successfully processed. Thank you for your purchase!",
"message_state_button": "Go back to Billing"
},
"DataTable": {
"no_results": "No results."
},
"Todos": {
"title_bar": "Todo List",
"title_bar_description": "View and manage your todo list",
"add_todo_button": "New todo"
},
"TodoTableColumns": {
"open_menu": "Open menu",
"edit": "Edit",
"delete": "Delete",
"title_header": "Title",
"message_header": "Message",
"created_at_header": "Created at"
},
"AddTodo": {
"title_bar": "Add Todo",
"add_todo_section_title": "Create a new todo",
"add_todo_section_description": "Fill in the form below to create a new todo"
},
"EditTodo": {
"title_bar": "Edit todo",
"edit_todo_section_title": "Modify todo",
"edit_todo_section_description": "Fill in the form below to edit the todo"
},
"TodoForm": {
"title_label": "Title",
"title_description": "Enter a descriptive title for your todo.",
"message_title": "Message",
"message_description": "Enter a detailed message for your todo.",
"submit_button": "Submit"
},
"Analytics": {
"title_bar": "Usage Analytics",
"title_bar_description": "Detailed analytics for your organization",

View file

@ -1,102 +1,23 @@
{
"Index": {
"meta_title": "SaaS Template - Le template SaaS parfait pour construire et mettre à l'échelle votre entreprise en toute simplicité.",
"meta_description": "Un template gratuit et open-source de landing page pour votre entreprise SaaS, construit avec React, TypeScript, Shadcn UI et Tailwind CSS."
"meta_title": "Roo Code Cloud",
"meta_description": "Gestion cloud pour Roo Code."
},
"Navbar": {
"sign_in": "Se connecter",
"sign_up": "S'inscrire",
"product": "Produit",
"docs": "Docs",
"blog": "Blog",
"community": "Communauté",
"company": "Entreprise"
},
"Hero": {
"follow_twitter": "Suivez @Ixartz sur Twitter",
"title": "Le parfait <important>SaaS template</important> pour construire et mettre à l'échelle votre entreprise en toute simplicité.",
"description": "Un template gratuit et open-source de landing page pour votre entreprise SaaS, construit avec React, TypeScript, Shadcn UI et Tailwind CSS.",
"primary_button": "Démarrer",
"secondary_button": "Mettez une étoile sur GitHub"
},
"Sponsors": {
"title": "Sponsorisé par"
},
"Features": {
"section_subtitle": "Fonctionnalités",
"section_title": "Débloquer le plein potentiel du SaaS Template",
"section_description": "Un template gratuit et open-source de landing page pour votre entreprise SaaS, construit avec React, TypeScript, Shadcn UI et Tailwind CSS.",
"feature1_title": "Node.js",
"feature2_title": "React",
"feature3_title": "Tailwind CSS",
"feature4_title": "TypeScript",
"feature5_title": "Shadcn UI",
"feature6_title": "ESLint",
"feature_description": "Un template gratuit et open-source de landing page pour votre entreprise SaaS, construit avec React, TypeScript, Shadcn UI et Tailwind CSS."
},
"Pricing": {
"section_subtitle": "Fonctionnalités",
"section_title": "Débloquer le plein potentiel du SaaS Template",
"section_description": "Un template gratuit et open-source de landing page pour votre entreprise SaaS, construit avec React, TypeScript, Shadcn UI et Tailwind CSS.",
"button_text": "Démarrer"
},
"PricingPlan": {
"free_plan_name": "Gratuit",
"premium_plan_name": "Premium",
"enterprise_plan_name": "Enterprise",
"free_plan_description": "Pour les particuliers",
"premium_plan_description": "Pour les petites équipes",
"enterprise_plan_description": "Pour les leaders de l'industrie",
"feature_team_member": "{number} membres",
"feature_website": "{number} sites internet",
"feature_storage": "{number} Go de stockage",
"feature_transfer": "{number} TB de transfert",
"feature_email_support": "Support par e-mail",
"plan_interval_month": "mois",
"plan_interval_year": "année",
"next_renew_date": "Votre abonnement sera renouvelé le {date}"
},
"FAQ": {
"question": "Lorem ipsum dolor sit amet, consectetur adipiscing elit?",
"answer": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam aliquam enim dui, id consequat turpis ullamcorper ac. Mauris id quam dolor. Nullam eu egestas turpis. Proin risus elit, sollicitudin in mi a, accumsan euismod turpis. In euismod mi sed diam tristique hendrerit."
},
"CTA": {
"title": "Vous êtes prêt?",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
"button_text": "Mettez une étoile sur GitHub"
"sign_up": "S'inscrire"
},
"Footer": {
"product": "Produit",
"docs": "Docs",
"blog": "Blog",
"community": "Communauté",
"company": "Entreprise",
"terms_of_service": "Conditions d'utilisation",
"privacy_policy": "Politique de confidentialité",
"designed_by": "Designé by <author></author>."
},
"ProtectFallback": {
"not_enough_permission": "Vous n'avez pas les permissions pour effectuer cette action"
},
"SignIn": {
"meta_title": "Se connecter",
"meta_description": "Connectez-vous à votre compte avec facilité."
},
"SignUp": {
"meta_title": "S'inscrire",
"meta_description": "Créez un compte sans effort grâce à notre processus d'inscription intuitif."
"privacy_policy": "Politique de confidentialité"
},
"DashboardLayout": {
"home": "Accueil",
"analytics": "Analytiques",
"todos": "Todos",
"members": "Membres",
"billing": "Facturation",
"settings": "Réglages"
},
"Dashboard": {
"meta_title": "Tableau de bord du SaaS Template",
"meta_description": "Un template gratuit et open-source de landing page pour votre entreprise SaaS, construit avec Next.js, TypeScript, Shadcn UI et Tailwind CSS."
"audit_logs": "Journaux d'audit",
"settings": "Réglages",
"provider_whitelist": "Liste blanche des fournisseurs"
},
"DashboardIndex": {
"title_bar": "Tableau de bord",
@ -105,17 +26,17 @@
"message_state_description": "Vous pouvez personnaliser cette page en modifiant le fichier dans <code>dashboard/page.tsx</code>",
"message_state_button": "Mettez une étoile sur GitHub",
"message_state_alternative": "Vous voulez plus de fonctionnalités en utilisant la même stack ? Essayez <url></url>.",
"analytics_title": "Analytique d'Utilisation",
"analytics_title": "Analytiques d'utilisation",
"analytics_description": "Métriques et statistiques d'utilisation de l'organisation",
"analytics_period_7_days": "7 derniers jours",
"analytics_period_30_days": "30 derniers jours",
"analytics_period_90_days": "90 derniers jours",
"analytics_tasks_started": "Tâches Commencées",
"analytics_tasks_completed": "Tâches Terminées",
"analytics_tokens_consumed": "Tokens Consommés",
"analytics_tasks_started": "Tâches commencées",
"analytics_tasks_completed": "Tâches terminées",
"analytics_tokens_consumed": "Tokens consommés",
"analytics_costs": "Coûts (USD)",
"analytics_llm_costs": "Coûts des Modèles LLM (USD)",
"analytics_active_developers": "Développeurs Actifs",
"analytics_llm_costs": "Coûts des modèles LLM (USD)",
"analytics_active_developers": "Développeurs actifs",
"analytics_view_details": "Voir les analytiques détaillées"
},
"UserProfile": {
@ -123,71 +44,31 @@
"title_bar_description": "Afficher et gérer votre profil utilisateur"
},
"OrganizationProfile": {
"title_bar": "Gestion de lorganisation",
"title_bar_description": "Gérer votre organisation"
"title_bar": "Gestion de l'organisation",
"title_bar_description": "Gérer votre organisation",
"provider_whitelist": "Liste blanche des fournisseurs",
"default_parameters": "Paramètres par défaut"
},
"Billing": {
"title_bar": "Facturation",
"title_bar_description": "Gérer votre facturation et votre abonnement",
"current_section_title": "Plan actuel",
"current_section_description": "Ajuster votre plan de paiement pour le mieux répondre à vos besoins",
"manage_subscription_button": "Gérer l'abonnement"
},
"BillingOptions": {
"current_plan": "Plan actuel",
"upgrade_plan": "Démarrer"
},
"CheckoutConfirmation": {
"title_bar": "Confirmation du paiement",
"message_state_title": "Paiement accepté",
"message_state_description": "Votre paiement a été traité avec succès. Merci pour votre achat !",
"message_state_button": "Revenir à la facturation"
},
"DataTable": {
"no_results": "Aucun résultat."
},
"Todos": {
"title_bar": "Liste de Todos",
"title_bar_description": "Afficher et gérer votre liste de todos",
"add_todo_button": "Nouveau todo"
},
"TodoTableColumns": {
"open_menu": "Ouvrir le menu",
"edit": "Modifier",
"delete": "Supprimer",
"title_header": "Titre",
"message_header": "Message",
"created_at_header": "Créé le"
},
"AddTodo": {
"title_bar": "Ajouter une todo",
"add_todo_section_title": "Créer une nouvelle todo",
"add_todo_section_description": "Remplissez le formulaire ci-dessous pour créer une nouvelle todo"
},
"EditTodo": {
"title_bar": "Editer le todo",
"edit_todo_section_title": "Modifier le todo",
"edit_todo_section_description": "Remplissez le formulaire ci-dessous pour modifier la todo"
},
"TodoForm": {
"title_label": "Titre",
"title_description": "Entrez un titre descriptif pour votre todo.",
"message_title": "Message",
"message_description": "Entrez un message détaillé pour votre todo.",
"submit_button": "Envoyer"
"ProviderWhitelist": {
"title": "Liste blanche des fournisseurs et paramètres par défaut",
"description": "Contrôlez quels fournisseurs d'IA sont autorisés et définissez les paramètres par défaut pour votre organisation",
"providers_section_title": "Fournisseurs autorisés",
"providers_section_description": "Sélectionnez quels fournisseurs et modèles d'IA sont autorisés à être utilisés",
"parameters_section_title": "Paramètres par défaut",
"parameters_section_description": "Définissez les paramètres par défaut globaux pour les appels aux modèles d'IA"
},
"Analytics": {
"title_bar": "Analytique d'Utilisation",
"title_bar": "Analytiques d'utilisation",
"title_bar_description": "Analytiques détaillées pour votre organisation",
"summary_title": "Résumé d'Utilisation",
"summary_title": "Résumé d'utilisation",
"period_7_days": "7 derniers jours",
"period_30_days": "30 derniers jours",
"period_90_days": "90 derniers jours",
"active_developers": "Développeurs Actifs",
"tasks_started": "Tâches Commencées",
"tasks_completed": "Tâches Terminées",
"tokens_consumed": "Tokens Consommés",
"llm_costs": "Coûts des Modèles LLM (USD)",
"active_developers": "Développeurs actifs",
"tasks_started": "Tâches commencées",
"tasks_completed": "Tâches terminées",
"tokens_consumed": "Tokens consommés",
"llm_costs": "Coûts des modèles LLM (USD)",
"view_mode_title": "Afficher Par",
"view_mode_developers": "Développeurs",
"view_mode_models": "Modèles",
@ -195,12 +76,12 @@
"filter_title": "Filtres",
"filter_developer": "Développeur",
"filter_model": "Modèle",
"filter_clear_all": "Effacer Tout",
"task_details_title": "Détails de la Tâche",
"filter_clear_all": "Effacer tout",
"task_details_title": "Détails de la tâche",
"task_details_close": "Fermer",
"pagination_prev": "Précédent",
"pagination_next": "Suivant",
"pagination_of": "de",
"pagination_of": "sur",
"pagination_page_size": "Taille de page",
"no_data": "Aucune donnée disponible",
"loading": "Chargement des données..."

View file

@ -1,5 +1,5 @@
import { cookies } from 'next/headers';
import { isLocale } from '@/lib/locale';
import { isLocale } from '@/i18n/locale';
import { getRequestConfig } from 'next-intl/server';
export default getRequestConfig(async (params) => {