Multi-Language Platform — 5 Languages

Trade in Your
Own Language.

Guro Markets supports 5 languages with full RTL support for Arabic. Every page, every button, every AI response — fully translated and culturally adapted.

English
English
LTR
"Trade Like a Master"
Arabic
العربية
RTL ←
"تداول كالمحترف"
French
Français
LTR
"Tradez comme un maître"
Spanish
Español
LTR
"Opera como un maestro"
Swahili
Kiswahili
LTR
"Fanya biashara kama bingwa"

Click any language card to see the platform in that language. Arabic includes full RTL layout mirroring.

Translation System

Full Platform Translation Keys

All UI strings are externalised into translation files. APEX AI responses are also dynamically translated per user's language preference.

KeyEnglishArabic عربيFrançaisEspañolKiswahili
nav.dashboardDashboardلوحة التحكمTableau de bordPanel de controlDashibodi
nav.tradeTrade Marketsتداول الأسواقMarchés de tradingMercados de tradingBiashara ya Masoko
nav.walletMy WalletمحفظتيMon portefeuilleMi carteraMkoba wangu
dashboard.depositDepositإيداعDépôtDepositarWeka pesa
trade.buyBuyشراءAcheterComprarNunua
trade.sellSellبيعVendreVenderUza
trade.stop_lossStop Lossوقف الخسارةStop lossStop lossSimamisha hasara
trade.take_profitTake Profitجني الأرباحPrendre profitTomar gananciasChukua faida
prop.profit_targetProfit Targetهدف الربحObjectif de profitObjetivo de gananciaLengo la faida
prop.on_trackOn Trackفي المسار الصحيحEn bonne voieEn buen caminoKatika mwelekeo
wallet.balanceTotal Balanceالرصيد الإجماليSolde totalSaldo totalSalio la jumla
ai.placeholderAsk AI anything…اسأل مساعد الذكاء الاصطناعي…Demandez à l'IA…Pregunta a la IA…Uliza AI chochote…
kyc.pendingKYC Pendingالتحقق معلقKYC en attenteKYC pendienteKYC inasubiri
common.confirmConfirmتأكيدConfirmerConfirmarThibitisha
common.cancelCancelإلغاءAnnulerCancelarGhairi
Implementation

i18n Architecture

// lib/i18n/index.ts — Core i18n system
import { createContext, useContext, useState, useEffect } from 'react';
import en from './locales/en.json';
import ar from './locales/ar.json';
import fr from './locales/fr.json';
import es from './locales/es.json';
import sw from './locales/sw.json';

export type Locale = 'en' | 'ar' | 'fr' | 'es' | 'sw';

export const LOCALES: Record<Locale, { name: string; native: string; flag: string; dir: 'ltr' | 'rtl' }> = {
  en: { name: 'English',  native: 'English',    flag: '🇬🇧', dir: 'ltr' },
  ar: { name: 'Arabic',   native: 'العربية',    flag: '🇸🇦', dir: 'rtl' },
  fr: { name: 'French',   native: 'Français',   flag: '🇫🇷', dir: 'ltr' },
  es: { name: 'Spanish',  native: 'Español',    flag: '🇪🇸', dir: 'ltr' },
  sw: { name: 'Swahili',  native: 'Kiswahili', flag: '🇰🇪', dir: 'ltr' },
};

const translations = { en, ar, fr, es, sw };

type I18nContextType = {
  locale: Locale;
  t: (key: string, params?: Record<string, string | number>) => string;
  setLocale: (locale: Locale) => void;
  dir: 'ltr' | 'rtl';
  isRTL: boolean;
};

const I18nContext = createContext<I18nContextType>({} as I18nContextType);

export function I18nProvider({ children }: { children: React.ReactNode }) {
  const [locale, setLocaleState] = useState<Locale>(() => {
    // Detect browser language or stored preference
    const stored = localStorage.getItem('guro_locale') as Locale;
    const browser = navigator.language.split('-')[0] as Locale;
    return stored || (Object.keys(LOCALES).includes(browser) ? browser : 'en');
  });

  const setLocale = (newLocale: Locale) => {
    setLocaleState(newLocale);
    localStorage.setItem('guro_locale', newLocale);
    document.documentElement.lang = newLocale;
    document.documentElement.dir = LOCALES[newLocale].dir;
    // Update font for Arabic
    document.body.style.fontFamily =
      newLocale === 'ar' ? "'Noto Sans Arabic', sans-serif" : "'Outfit', sans-serif";
  };

  useEffect(() => { setLocale(locale); }, []);

  const t = (key: string, params?: Record<string, string | number>) => {
    const dict = translations[locale] as Record<string, string>;
    let str = dict[key] || translations.en[key as keyof typeof translations.en] || key;
    if (params) {
      Object.entries(params).forEach(([k, v]) => {
        str = str.replace(new RegExp(`{{${k}}}`, 'g'), String(v));
      });
    }
    return str;
  };

  return (
    <I18nContext.Provider value={{ locale, t, setLocale, dir: LOCALES[locale].dir, isRTL: LOCALES[locale].dir === 'rtl' }}>
      {children}
    </I18nContext.Provider>
  );
}

export const useI18n = () => useContext(I18nContext);
// locales/ar.json — Arabic Translation (full excerpt)
{
  // Navigation
  "nav.dashboard":       "لوحة التحكم",
  "nav.trade":           "تداول الأسواق",
  "nav.positions":       "المراكز المفتوحة",
  "nav.history":         "سجل التداول",
  "nav.watchlist":       "قائمة المتابعة",
  "nav.wallet":          "المحفظة",
  "nav.prop_challenge":  "تحدي التمويل",
  "nav.copy_trading":    "تداول النسخ",
  "nav.ai_assistant":    "مساعد الذكاء الاصطناعي",
  "nav.settings":        "الإعدادات",
  "nav.sign_out":        "تسجيل الخروج",

  // Dashboard
  "dashboard.greeting":        "صباح الخير، {{name}} 👋",
  "dashboard.markets_open":     "الأسواق مفتوحة",
  "dashboard.balance":          "الرصيد",
  "dashboard.open_pnl":         "الربح والخسارة المفتوح",
  "dashboard.open_trades":       "الصفقات المفتوحة",
  "dashboard.prop_progress":     "تقدم تحدي التمويل",
  "dashboard.deposit":          "إيداع",
  "dashboard.trade_now":        "تداول الآن",
  "dashboard.view_all":         "عرض الكل",
  "dashboard.edit":             "تعديل",
  "dashboard.open_positions":   "المراكز المفتوحة",
  "dashboard.watchlist":        "قائمة المتابعة",

  // Trading
  "trade.buy":             "شراء",
  "trade.sell":            "بيع",
  "trade.lot_size":        "حجم العقد",
  "trade.stop_loss":       "وقف الخسارة",
  "trade.take_profit":     "جني الأرباح",
  "trade.leverage":        "الرافعة المالية",
  "trade.margin":          "الهامش المطلوب",
  "trade.spread":          "الفارق السعري",
  "trade.commission":      "العمولة",
  "trade.execute_buy":     "تنفيذ أمر الشراء",
  "trade.execute_sell":    "تنفيذ أمر البيع",

  // AI
  "ai.title":             "مساعد أبيكس الذكي",
  "ai.online":            "متصل — يراقب حسابك",
  "ai.placeholder":       "اسأل مساعد الذكاء الاصطناعي أي شيء…",
  "ai.analyse":           "تحليل",
  "ai.best_setup":        "أفضل إعداد",
  "ai.my_risk":           "مستوى المخاطرة",
  "ai.news_today":        "أخبار اليوم",

  // Prop Challenge
  "prop.title":            "تحدي التمويل",
  "prop.profit_target":    "هدف الربح",
  "prop.daily_loss":       "حد الخسارة اليومية",
  "prop.max_drawdown":     "الحد الأقصى للسحب",
  "prop.trading_days":     "أيام التداول",
  "prop.on_track":         "في المسار الصحيح",
  "prop.request_payout":   "طلب السحب",

  // Wallet
  "wallet.title":          "محفظتي",
  "wallet.deposit":        "إيداع",
  "wallet.withdraw":       "سحب",
  "wallet.total_balance":  "الرصيد الإجمالي",
  "wallet.equity":         "حقوق الملكية",
  "wallet.margin_used":    "الهامش المستخدم",
  "wallet.free_margin":    "الهامش المتاح",

  // KYC
  "kyc.pending":           "التحقق من الهوية معلق",
  "kyc.verified":          "تم التحقق ✓",
  "kyc.complete":          "إكمال التحقق من الهوية",

  // Common
  "common.loading":        "جار التحميل…",
  "common.error":          "حدث خطأ",
  "common.success":        "تم بنجاح",
  "common.cancel":         "إلغاء",
  "common.confirm":        "تأكيد",
  "common.back":           "رجوع",
  "common.next":           "التالي",
  "common.save":           "حفظ",
  "common.close":          "إغلاق"
}
/* styles/rtl.css — RTL Layout Overrides */

/* ── Base RTL document ── */
[dir="rtl"] {
  text-align: right;
  font-family: 'Noto Sans Arabic', 'Outfit', sans-serif;
}

/* ── Flex direction reversal ── */
[dir="rtl"] .flex-row     { flex-direction: row-reverse; }
[dir="rtl"] .nav-items   { flex-direction: row-reverse; }
[dir="rtl"] .card-header { flex-direction: row-reverse; }
[dir="rtl"] .stat-row    { flex-direction: row-reverse; }

/* ── Sidebar ── */
[dir="rtl"] #sidebar {
  left: auto;
  right: 0;
  border-right: none;
  border-left: 1px solid var(--bdr3);
  transform: translateX(105%);
}
[dir="rtl"] #sidebar.open { transform: translateX(0); }
[dir="rtl"] #main { margin-left: 0; margin-right: var(--sideW, 0); }

/* ── Active border indicator (left → right) ── */
[dir="rtl"] .wl-item.active {
  border-left: none;
  border-right: 2px solid var(--gold);
}

/* ── Margin/padding mirroring ── */
[dir="rtl"] .pos-pl,
[dir="rtl"] .wl-right,
[dir="rtl"] .hist-right { margin-left: 0; margin-right: auto; }

[dir="rtl"] .pl-indent { padding-left: 0; padding-right: 16px; }
[dir="rtl"] .ml-auto   { margin-left: 0; margin-right: auto; }

/* ── Progress bars (visual only, no direction change) ── */
[dir="rtl"] .rule-bar,
[dir="rtl"] .pt-bar { direction: ltr; }

/* ── Arabic number formatting ── */
[dir="rtl"] .mono-number { font-family: 'JetBrains Mono', monospace; unicode-bidi: plaintext; }

/* ── Bottom nav ── */
[dir="rtl"] #botnav { flex-direction: row-reverse; }

/* ── Form inputs ── */
[dir="rtl"] input,
[dir="rtl"] textarea,
[dir="rtl"] select { text-align: right; direction: rtl; }

/* ── Exception: numbers always LTR ── */
[dir="rtl"] .price-val,
[dir="rtl"] .pnl-val,
[dir="rtl"] .account-id { direction: ltr; unicode-bidi: embed; }

/* ── Toast messages ── */
[dir="rtl"] .toast { font-family: 'Noto Sans Arabic', sans-serif; }

/* ── Chevrons / arrows direction flip ── */
[dir="rtl"] .chevron-right::after { content: '←'; }
[dir="rtl"] .chevron-left::after  { content: '→'; }
[dir="rtl"] .back-arrow svg   { transform: scaleX(-1); }

/* ── Next.js App Router — next-intl config ── */
// next.config.ts
import createNextIntlPlugin from 'next-intl/plugin';
const withNextIntl = createNextIntlPlugin('./i18n.ts');
export default withNextIntl({
  i18n: {
    locales: ['en', 'ar', 'fr', 'es', 'sw'],
    defaultLocale: 'en',
  },
});
// lib/ai/translate.ts — AI-powered dynamic translation
// APEX AI responses are dynamically generated in user's language

import Apex from '@apex-ai/sdk';
import { type Locale, LOCALES } from '../i18n';

const client = new Apex();

// Generate AI trading analysis in user's language
export async function getLocalizedAIAnalysis(
  pair: string,
  data: object,
  locale: Locale
): Promise<string> {
  const lang = LOCALES[locale].name;
  const isRTL = LOCALES[locale].dir === 'rtl';

  const systemPrompt = `
    You are APEX, the AI trading assistant for Guro Markets.
    IMPORTANT: Respond ENTIRELY in ${lang}.
    ${isRTL ? 'Use proper RTL Arabic script. Use Arabic financial terminology.' : ''}
    Be concise (2-3 sentences max). Use the same professional tone.
    Numbers and tickers (XAU/USD, etc.) stay in their original format.
  `;

  const response = await client.messages.create({
    model: 'apex-core-v2',
    max_tokens: 256,
    system: systemPrompt,
    messages: [{
      role: 'user',
      content: `Analyse this trading data and give a brief recommendation: ${JSON.stringify(data)}`
    }]
  });

  return response.content[0].type === 'text' ? response.content[0].text : '';
}

// Batch translate static strings (for server-side pre-rendering)
export async function translateStrings(
  strings: string[],
  targetLocale: Locale
): Promise<Record<string, string>> {
  if (targetLocale === 'en') {
    return Object.fromEntries(strings.map(s => [s, s]));
  }

  const lang = LOCALES[targetLocale].name;
  const response = await client.messages.create({
    model: 'apex-core-v2',
    max_tokens: 2048,
    messages: [{
      role: 'user',
      content: `Translate these UI strings to ${lang}. Return JSON only.
               Preserve {{variables}} exactly. Financial/trading terms use industry-standard ${lang} terminology.
               Strings: ${JSON.stringify(strings)}`
    }]
  });

  try {
    const text = response.content[0].type === 'text' ? response.content[0].text : '{}';
    return JSON.parse(text.replace(/```json|```/g, ''));
  } catch {
    return Object.fromEntries(strings.map(s => [s, s]));
  }
}