diff --git a/packages/client/lib/i18n.ts b/packages/client/lib/i18n.ts new file mode 100644 index 00000000..d66799b4 --- /dev/null +++ b/packages/client/lib/i18n.ts @@ -0,0 +1,70 @@ +/** + * Lightweight i18n framework for Traqora client. + */ + +import { useState, useEffect } from 'react'; + +export const en = { + 'wallet.status': 'Wallet Status', + 'wallet.disconnected': 'Not Connected', + 'wallet.connected': 'Connected', + 'wallet.connect': 'Connect Wallet', + 'wallet.connecting': 'Connecting...', + 'wallet.linking': 'Linking...', + 'wallet.description': 'Connect your Stellar wallet to get started.', + 'wallet.info.title': 'Wallet Information', + 'wallet.info.description': 'Your connected Stellar wallet details.', + 'wallet.address': 'Address', + 'wallet.network': 'Network', + 'wallet.type': 'Wallet Type', + 'wallet.copy': 'Copy Address', + 'wallet.copied': 'Copied!', + 'wallet.explorer': 'View on Explorer', + 'wallet.disconnect': 'Disconnect Wallet', +}; + +export type TranslationKeys = keyof typeof en; + +const dictionaries: Record> = { + en, +}; + +let currentLocale = 'en'; + +export function setLocale(locale: string) { + if (dictionaries[locale]) { + currentLocale = locale; + } +} + +export function getLocale(): string { + return currentLocale; +} + +export function t(key: TranslationKeys, params?: Record): string { + const dict = dictionaries[currentLocale] || dictionaries.en; + let text = dict[key] || dictionaries.en[key] || key; + if (params) { + for (const [pKey, pVal] of Object.entries(params)) { + text = text.replace(new RegExp(`\\{${pKey}\\}`, 'g'), String(pVal)); + } + } + return text; +} + +export function useTranslation() { + const [locale, setLocState] = useState(currentLocale); + + useEffect(() => { + setLocState(currentLocale); + }, []); + + return { + t, + locale, + setLocale: (l: string) => { + setLocale(l); + setLocState(l); + }, + }; +} diff --git a/packages/client/lib/stellar-wallet-connect/components/WalletInfo.tsx b/packages/client/lib/stellar-wallet-connect/components/WalletInfo.tsx index a0c5f1f3..967d2699 100644 --- a/packages/client/lib/stellar-wallet-connect/components/WalletInfo.tsx +++ b/packages/client/lib/stellar-wallet-connect/components/WalletInfo.tsx @@ -15,6 +15,7 @@ import { useEffect, useState } from 'react'; import { CheckCircle, Copy, ExternalLink, Wallet, XCircle } from 'lucide-react'; import useWalletStore from '../store'; +import { t } from '../../i18n'; import { useWallet } from '../use-wallet'; import type { WalletInfoProps, StellarNetwork } from '../types'; @@ -95,15 +96,15 @@ export function WalletInfo({ >

- Connect your Stellar wallet to get started. + {t('wallet.description')}

@@ -131,10 +132,10 @@ export function WalletInfo({ >

- Your connected Stellar wallet details. + {t('wallet.info.description')}

diff --git a/packages/client/tests/unit/i18n.test.ts b/packages/client/tests/unit/i18n.test.ts new file mode 100644 index 00000000..226ef0cd --- /dev/null +++ b/packages/client/tests/unit/i18n.test.ts @@ -0,0 +1,15 @@ +import { describe, it, expect } from '@jest/globals'; +import { t, setLocale, getLocale, en } from '../../lib/i18n'; + +describe('i18n framework', () => { + it('returns correct translation for key', () => { + setLocale('en'); + expect(getLocale()).toBe('en'); + expect(t('wallet.connect')).toBe(en['wallet.connect']); + }); + + it('falls back to key if missing', () => { + // @ts-expect-error testing invalid key + expect(t('non.existent.key')).toBe('non.existent.key'); + }); +});