Adding New Languages

This guide explains how to add support for new languages to your application using the internationalization package.

Overview

The internationalization package currently supports English (en), Turkish (tr), Spanish (es), and German (de). You can add support for additional languages by following these steps:

  1. Update configuration files
  2. Create translation files
  3. Test the new language

Step 1: Update Configuration Files

First, you need to update the configuration files to include the new language:

Update languine.json

Add the new language code to the targets array in languine.json:

{
  "locale": {
    "source": "en",
    "targets": ["es", "de", "tr", "fr"] // Added "fr" for French
  },
  "files": {
    "json": {
      "include": ["dictionaries/[locale].json"]
    }
  }
}

Update i18nConfig.ts

Add the new language code to the locales array in i18nConfig.ts:

export const i18nConfig = {
  defaultLocale: 'en',
  locales: ['en', 'tr', 'es', 'de', 'fr'], // Added "fr" for French
  localePrefix: 'as-needed'
}

Step 2: Create Translation Files

You need to create translation files for the new language in both the dictionaries and locales directories:

Create Dictionary File

Create a new file in the dictionaries directory with the name of your language code:

# Example for French
touch dictionaries/fr.json

Then, copy the structure from the English dictionary file and translate the content:

{
  "web": {
    "global": {
      "primaryCta": "Réserver un appel",
      "secondaryCta": "S'inscrire"
    },
    "header": {
      "home": "Accueil",
      "product": {
        "title": "Produit",
        "description": "Gérer une petite entreprise aujourd'hui est déjà difficile.",
        "pricing": "Tarification"
      },
      "blog": "Blog",
      "docs": "Documentation",
      "contact": "Contact",
      "signIn": "Se connecter",
      "signUp": "Commencer"
    },
    // ... translate all other entries
  }
}

Start by translating the most important sections first, such as navigation, common buttons, and main page content. You can gradually translate the rest of the content over time.

Create Locale File

Create a new file in the locales directory with the name of your language code:

# Example for French
touch locales/fr.json

Then, add the basic translations:

{
  "greeting": "Bonjour",
  "today": "Aujourd'hui est {date}"
}

Step 3: Generate Translations (Optional)

If you have a large number of translations, you can use the built-in translation script to generate translations automatically:

npm run translate

This will use the Languine tool to generate translations for all target languages based on the source language (English).

Automatically generated translations may not be perfect. Always review and edit them for accuracy and cultural appropriateness.

Step 4: Test the New Language

After adding the new language, test it to make sure everything works correctly:

  1. Start your development server:

    npm run dev
    
  2. Visit your application with the new locale path:

    http://localhost:3000/fr
    
  3. Check that the content is displayed in the new language.

  4. Test navigation, forms, and other interactive elements to ensure translations are applied correctly.

Handling Special Characters and RTL Languages

Special Characters

Some languages use special characters that may require specific handling:

// Make sure your HTML has the correct charset
<html lang={locale} dir={isRTL(locale) ? 'rtl' : 'ltr'}>
  <head>
    <meta charSet="UTF-8" />
    {/* Other head elements */}
  </head>
  <body>
    {/* Content */}
  </body>
</html>

Right-to-Left (RTL) Languages

For languages that are read from right to left (like Arabic or Hebrew), you need to add additional support:

  1. Create a helper function to identify RTL languages:
// utils/language.ts
export function isRTL(locale: string): boolean {
  const rtlLocales = ['ar', 'he', 'fa', 'ur'];
  return rtlLocales.includes(locale);
}
  1. Update your layout to apply RTL direction when needed:
// app/[locale]/layout.tsx
import { getDictionary } from '@repo/internationalization';
import { isRTL } from '@/utils/language';

export default async function RootLayout({ 
  children, 
  params 
}: { 
  children: React.ReactNode;
  params: { locale: string };
}) {
  const dictionary = await getDictionary(params.locale);
  
  return (
    <html lang={params.locale} dir={isRTL(params.locale) ? 'rtl' : 'ltr'}>
      <body>
        {/* Layout content */}
        {children}
      </body>
    </html>
  );
}
  1. Add CSS to handle RTL styling:
/* For RTL languages */
[dir="rtl"] {
  text-align: right;
}

[dir="rtl"] .some-component {
  margin-left: 0;
  margin-right: 1rem;
}

Best Practices for Multilingual Content

Examples

Adding French Language Support

Here’s a complete example of adding French language support:

  1. Update languine.json:
{
  "locale": {
    "source": "en",
    "targets": ["es", "de", "tr", "fr"]
  },
  "files": {
    "json": {
      "include": ["dictionaries/[locale].json"]
    }
  }
}
  1. Update i18nConfig.ts:
export const i18nConfig = {
  defaultLocale: 'en',
  locales: ['en', 'tr', 'es', 'de', 'fr'],
  localePrefix: 'as-needed'
}
  1. Create dictionaries/fr.json with translated content:
{
  "web": {
    "global": {
      "primaryCta": "Réserver un appel",
      "secondaryCta": "S'inscrire"
    },
    "header": {
      "home": "Accueil",
      "product": {
        "title": "Produit",
        "description": "Gérer une petite entreprise aujourd'hui est déjà difficile.",
        "pricing": "Tarification"
      },
      "blog": "Blog",
      "docs": "Documentation",
      "contact": "Contact",
      "signIn": "Se connecter",
      "signUp": "Commencer"
    }
    // ... more translations
  }
}
  1. Create locales/fr.json:
{
  "greeting": "Bonjour",
  "today": "Aujourd'hui est {date}"
}
  1. Update your language switcher to include French:
const localeNames: Record<string, string> = {
  en: 'English',
  tr: 'Türkçe',
  es: 'Español',
  de: 'Deutsch',
  fr: 'Français'
};

Next Steps