@gtcx/i18n 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # @gtcx/i18n
2
+
3
+ Multi-language support system for GTCX Protocol — country-agnostic internationalization with cultural adaptation.
4
+
5
+ ## Features
6
+
7
+ - **50+ Languages** — Primary and local dialect support
8
+ - **Cultural Context** — Language that feels native, not translated
9
+ - **Offline-First** — Full i18n capabilities without connectivity
10
+ - **AI-Native** — Agents auto-detect and adapt to user language
11
+ - **RTL Support** — Right-to-left language handling
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ pnpm add @gtcx/i18n
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```typescript
22
+ import { I18nService, CulturalContext } from '@gtcx/i18n';
23
+
24
+ // Initialize with country context
25
+ const i18n = new I18nService({
26
+ country: 'ghana',
27
+ primaryLanguage: 'en',
28
+ localLanguages: ['tw', 'gaa', 'ee'], // Twi, Ga, Ewe
29
+ fallbackLanguage: 'en',
30
+ });
31
+
32
+ // Translate with cultural context
33
+ const message = i18n.t('compliance.violation_warning', {
34
+ context: 'formal', // Adapts tone for authority figures
35
+ dialect: 'tw', // Twi dialect
36
+ });
37
+
38
+ // AI agent language detection
39
+ const detectedLang = await i18n.detectLanguage(userInput);
40
+ const response = i18n.t('welcome', { lang: detectedLang });
41
+ ```
42
+
43
+ ## Cultural Adaptation
44
+
45
+ The i18n system goes beyond translation:
46
+
47
+ ```typescript
48
+ // Cultural context affects more than words
49
+ const culturalContext = i18n.getCulturalContext('ghana');
50
+
51
+ culturalContext.communicationStyle; // 'formal', 'community-oriented'
52
+ culturalContext.decisionMaking; // 'consensus', 'elder-consultation'
53
+ culturalContext.honorifics; // true (use respectful titles)
54
+ culturalContext.traditionalKnowledge; // Integration points
55
+ ```
56
+
57
+ ## Supported Languages by Region
58
+
59
+ ### West Africa
60
+
61
+ - English, Twi, Ga, Ewe, Dagbani (Ghana)
62
+ - English, Yoruba, Igbo, Hausa (Nigeria)
63
+ - French, Wolof (Senegal)
64
+
65
+ ### East Africa
66
+
67
+ - Swahili, English, Kikuyu, Luo (Kenya)
68
+ - Swahili, English, Sukuma (Tanzania)
69
+
70
+ ### Latin America
71
+
72
+ - Spanish, Quechua, Aymara (Peru)
73
+ - Spanish, Wayuu, Emberá (Colombia)
74
+
75
+ ### Global
76
+
77
+ - English, French, Spanish, Portuguese, Arabic, Chinese, Hindi
78
+
79
+ ## Architecture
80
+
81
+ ```
82
+ packages/i18n/
83
+ ├── src/
84
+ │ ├── index.ts # Main exports
85
+ │ ├── service.ts # I18nService class
86
+ │ ├── cultural-context.ts # Cultural adaptation logic
87
+ │ ├── language-detector.ts # AI language detection
88
+ │ ├── offline-store.ts # Offline translation cache
89
+ │ └── types.ts # TypeScript definitions
90
+ ├── locales/ # Translation files
91
+ │ ├── en/
92
+ │ ├── sw/ # Swahili
93
+ │ ├── es/ # Spanish
94
+ │ └── ...
95
+ └── cultural/ # Cultural context configs
96
+ ├── ghana.yaml
97
+ ├── kenya.yaml
98
+ └── ...
99
+ ```
100
+
101
+ ## Related Packages
102
+
103
+ - `@gtcx/accessibility` — Tech literacy and WCAG compliance
104
+ - `@gtcx/offline-sync` — Offline-first data synchronization
@@ -0,0 +1,374 @@
1
+ /**
2
+ * Type definitions for @gtcx/i18n
3
+ */
4
+ interface LanguageConfig {
5
+ /** ISO 639-1 language code */
6
+ code: string;
7
+ /** Language name in English */
8
+ name: string;
9
+ /** Language name in native script */
10
+ nativeName: string;
11
+ /** Countries where this language is used */
12
+ countries: string[];
13
+ /** Writing system (latin, arabic, devanagari, etc.) */
14
+ writingSystem: string;
15
+ /** Text direction */
16
+ direction: 'ltr' | 'rtl';
17
+ /** Recommended font families */
18
+ fontFamily: string;
19
+ /** Fallback fonts */
20
+ fallbackFonts: string[];
21
+ /** Whether language uses formal/informal forms */
22
+ formalForms: boolean;
23
+ /** Whether language uses honorifics */
24
+ honorifics: boolean;
25
+ }
26
+ interface TranslationEntry {
27
+ /** Unique key for this translation */
28
+ key: string;
29
+ /** Source language code */
30
+ sourceLanguage: string;
31
+ /** Target language code */
32
+ targetLanguage: string;
33
+ /** Original text */
34
+ sourceText: string;
35
+ /** Translated text */
36
+ targetText: string;
37
+ /** Context for translation (formal, informal, technical, etc.) */
38
+ context: string;
39
+ /** Category (ui, compliance, legal, etc.) */
40
+ category: string;
41
+ /** Cultural notes for translators */
42
+ culturalNotes: string;
43
+ /** Whether translation has been verified */
44
+ verified: boolean;
45
+ /** Who verified this translation */
46
+ verifiedBy?: string;
47
+ /** Quality score (0-1) */
48
+ qualityScore: number;
49
+ /** Last update timestamp */
50
+ lastUpdated: string;
51
+ }
52
+ interface CulturalContextConfig {
53
+ /** Country code (ISO 3166-1 alpha-2) */
54
+ countryCode: string;
55
+ /** Core cultural values */
56
+ culturalValues: string[];
57
+ /** Communication style preferences */
58
+ communicationStyle: 'formal' | 'informal' | 'community-oriented' | 'hierarchical';
59
+ /** Decision-making patterns */
60
+ decisionMaking: 'individual' | 'consensus' | 'elder-consultation' | 'community';
61
+ /** Conflict resolution approach */
62
+ conflictResolution: string;
63
+ /** Traditional knowledge to integrate */
64
+ traditionalKnowledge: string[];
65
+ /** Local examples to use in explanations */
66
+ localExamples: string[];
67
+ /** Topics to avoid */
68
+ taboos: string[];
69
+ /** Local celebrations to acknowledge */
70
+ celebrations: string[];
71
+ /** Community structure description */
72
+ communityStructure: string;
73
+ }
74
+ interface I18nOptions {
75
+ /** Country code for cultural context */
76
+ country: string;
77
+ /** Primary language code */
78
+ primaryLanguage: string;
79
+ /** Additional local language codes */
80
+ localLanguages?: string[];
81
+ /** Fallback language if translation not found */
82
+ fallbackLanguage: string;
83
+ /** Enable offline translation caching */
84
+ offlineEnabled?: boolean;
85
+ /** Custom translations to merge */
86
+ customTranslations?: Record<string, TranslationEntry>;
87
+ }
88
+ interface TranslateOptions {
89
+ /** Target language (defaults to primaryLanguage) */
90
+ lang?: string;
91
+ /** Context for translation */
92
+ context?: 'formal' | 'informal' | 'technical' | 'legal';
93
+ /** Specific dialect */
94
+ dialect?: string;
95
+ /** Interpolation values */
96
+ values?: Record<string, string | number>;
97
+ /** Plural count for pluralization */
98
+ count?: number;
99
+ }
100
+ interface DetectionResult {
101
+ /** Detected language code */
102
+ language: string;
103
+ /** Confidence score (0-1) */
104
+ confidence: number;
105
+ /** Possible alternatives */
106
+ alternatives: Array<{
107
+ language: string;
108
+ confidence: number;
109
+ }>;
110
+ }
111
+
112
+ /**
113
+ * Cultural Context Management
114
+ * Provides cultural adaptation beyond translation
115
+ */
116
+
117
+ /**
118
+ * Get cultural context for a country
119
+ */
120
+ declare function getCulturalContext(countryCode: string): CulturalContextConfig | null;
121
+ /**
122
+ * Cultural context class with helper methods
123
+ */
124
+ declare class CulturalContext {
125
+ private config;
126
+ constructor(countryCode: string);
127
+ /**
128
+ * Check if formal communication style is expected
129
+ */
130
+ get usesFormalAddress(): boolean;
131
+ /**
132
+ * Check if community consultation is expected for decisions
133
+ */
134
+ get requiresCommunityConsultation(): boolean;
135
+ /**
136
+ * Get local examples for explanations
137
+ */
138
+ getLocalExamples(): string[];
139
+ /**
140
+ * Check if a topic should be avoided
141
+ */
142
+ isTaboo(topic: string): boolean;
143
+ /**
144
+ * Get traditional knowledge integration points
145
+ */
146
+ getTraditionalKnowledge(): string[];
147
+ /**
148
+ * Get raw config
149
+ */
150
+ toJSON(): CulturalContextConfig;
151
+ }
152
+
153
+ /**
154
+ * Translation engine with fallback chain.
155
+ *
156
+ * Supports interpolation (`{name}`), pluralization, and a locale
157
+ * fallback chain: exact locale → base language → fallback language.
158
+ */
159
+
160
+ type TranslationMap = Record<string, string | Record<string, string>>;
161
+ type TranslationCatalog = Record<string, TranslationMap>;
162
+ interface TranslatorOptions {
163
+ /** Primary locale (e.g. 'tw', 'sw', 'en') */
164
+ locale: string;
165
+ /** Fallback locale when a key is missing. Defaults to `'en'`. */
166
+ fallbackLocale?: string;
167
+ /** Translation dictionaries keyed by locale. */
168
+ catalog: TranslationCatalog;
169
+ }
170
+ /**
171
+ * Lightweight translation function factory.
172
+ *
173
+ * ```ts
174
+ * const { t } = createTranslator({
175
+ * locale: 'tw',
176
+ * catalog: {
177
+ * en: { greeting: 'Hello, {name}!' },
178
+ * tw: { greeting: 'Akwaaba, {name}!' },
179
+ * },
180
+ * });
181
+ * t('greeting', { values: { name: 'Kofi' } }); // → 'Akwaaba, Kofi!'
182
+ * ```
183
+ */
184
+ declare function createTranslator(options: TranslatorOptions): {
185
+ t: (key: string, opts?: TranslateOptions) => string;
186
+ locale: string;
187
+ fallbackLocale: string;
188
+ };
189
+
190
+ /**
191
+ * Locale-aware formatters using the native `Intl` APIs.
192
+ *
193
+ * These wrappers exist so that GTCX apps don't import `Intl` directly
194
+ * and can be tested/mocked uniformly.
195
+ */
196
+ /** Format a number according to locale conventions. */
197
+ declare function formatNumber(value: number, locale: string, options?: Intl.NumberFormatOptions): string;
198
+ /** Format a currency value. */
199
+ declare function formatCurrency(value: number, locale: string, currency: string, options?: Omit<Intl.NumberFormatOptions, 'style' | 'currency'>): string;
200
+ /** Format a date. */
201
+ declare function formatI18nDate(date: Date | string, locale: string, options?: Intl.DateTimeFormatOptions): string;
202
+ /** Format a relative time (e.g. "3 days ago"). */
203
+ declare function formatRelativeTime(value: number, unit: Intl.RelativeTimeFormatUnit, locale: string): string;
204
+
205
+ /**
206
+ * RTL (Right-to-Left) detection utilities.
207
+ */
208
+ /** Returns `true` if the given locale code uses a right-to-left script. */
209
+ declare function isRTL(locale: string): boolean;
210
+ /** Returns `'rtl'` or `'ltr'` for use in HTML `dir` attributes. */
211
+ declare function getDirection(locale: string): 'rtl' | 'ltr';
212
+
213
+ /**
214
+ * Supported languages and language families
215
+ */
216
+ declare const SUPPORTED_LANGUAGES: {
217
+ readonly en: {
218
+ readonly name: "English";
219
+ readonly nativeName: "English";
220
+ readonly direction: "ltr";
221
+ };
222
+ readonly fr: {
223
+ readonly name: "French";
224
+ readonly nativeName: "Français";
225
+ readonly direction: "ltr";
226
+ };
227
+ readonly es: {
228
+ readonly name: "Spanish";
229
+ readonly nativeName: "Español";
230
+ readonly direction: "ltr";
231
+ };
232
+ readonly pt: {
233
+ readonly name: "Portuguese";
234
+ readonly nativeName: "Português";
235
+ readonly direction: "ltr";
236
+ };
237
+ readonly ar: {
238
+ readonly name: "Arabic";
239
+ readonly nativeName: "العربية";
240
+ readonly direction: "rtl";
241
+ };
242
+ readonly zh: {
243
+ readonly name: "Chinese";
244
+ readonly nativeName: "中文";
245
+ readonly direction: "ltr";
246
+ };
247
+ readonly hi: {
248
+ readonly name: "Hindi";
249
+ readonly nativeName: "हिन्दी";
250
+ readonly direction: "ltr";
251
+ };
252
+ readonly tw: {
253
+ readonly name: "Twi";
254
+ readonly nativeName: "Twi";
255
+ readonly direction: "ltr";
256
+ };
257
+ readonly gaa: {
258
+ readonly name: "Ga";
259
+ readonly nativeName: "Gã";
260
+ readonly direction: "ltr";
261
+ };
262
+ readonly ee: {
263
+ readonly name: "Ewe";
264
+ readonly nativeName: "Eʋegbe";
265
+ readonly direction: "ltr";
266
+ };
267
+ readonly dag: {
268
+ readonly name: "Dagbani";
269
+ readonly nativeName: "Dagbanli";
270
+ readonly direction: "ltr";
271
+ };
272
+ readonly yo: {
273
+ readonly name: "Yoruba";
274
+ readonly nativeName: "Yorùbá";
275
+ readonly direction: "ltr";
276
+ };
277
+ readonly ig: {
278
+ readonly name: "Igbo";
279
+ readonly nativeName: "Igbo";
280
+ readonly direction: "ltr";
281
+ };
282
+ readonly ha: {
283
+ readonly name: "Hausa";
284
+ readonly nativeName: "Hausa";
285
+ readonly direction: "ltr";
286
+ };
287
+ readonly wo: {
288
+ readonly name: "Wolof";
289
+ readonly nativeName: "Wolof";
290
+ readonly direction: "ltr";
291
+ };
292
+ readonly sw: {
293
+ readonly name: "Swahili";
294
+ readonly nativeName: "Kiswahili";
295
+ readonly direction: "ltr";
296
+ };
297
+ readonly ki: {
298
+ readonly name: "Kikuyu";
299
+ readonly nativeName: "Gĩkũyũ";
300
+ readonly direction: "ltr";
301
+ };
302
+ readonly luo: {
303
+ readonly name: "Luo";
304
+ readonly nativeName: "Dholuo";
305
+ readonly direction: "ltr";
306
+ };
307
+ readonly kam: {
308
+ readonly name: "Kamba";
309
+ readonly nativeName: "Kikamba";
310
+ readonly direction: "ltr";
311
+ };
312
+ readonly kln: {
313
+ readonly name: "Kalenjin";
314
+ readonly nativeName: "Kalenjin";
315
+ readonly direction: "ltr";
316
+ };
317
+ readonly suk: {
318
+ readonly name: "Sukuma";
319
+ readonly nativeName: "Kisukuma";
320
+ readonly direction: "ltr";
321
+ };
322
+ readonly hay: {
323
+ readonly name: "Haya";
324
+ readonly nativeName: "Kihaya";
325
+ readonly direction: "ltr";
326
+ };
327
+ readonly qu: {
328
+ readonly name: "Quechua";
329
+ readonly nativeName: "Runasimi";
330
+ readonly direction: "ltr";
331
+ };
332
+ readonly ay: {
333
+ readonly name: "Aymara";
334
+ readonly nativeName: "Aymar aru";
335
+ readonly direction: "ltr";
336
+ };
337
+ readonly gn: {
338
+ readonly name: "Guarani";
339
+ readonly nativeName: "Avañe'ẽ";
340
+ readonly direction: "ltr";
341
+ };
342
+ readonly bn: {
343
+ readonly name: "Bengali";
344
+ readonly nativeName: "বাংলা";
345
+ readonly direction: "ltr";
346
+ };
347
+ readonly ta: {
348
+ readonly name: "Tamil";
349
+ readonly nativeName: "தமிழ்";
350
+ readonly direction: "ltr";
351
+ };
352
+ readonly te: {
353
+ readonly name: "Telugu";
354
+ readonly nativeName: "తెలుగు";
355
+ readonly direction: "ltr";
356
+ };
357
+ readonly mr: {
358
+ readonly name: "Marathi";
359
+ readonly nativeName: "मराठी";
360
+ readonly direction: "ltr";
361
+ };
362
+ };
363
+ declare const LANGUAGE_FAMILIES: {
364
+ readonly niger_congo: readonly ["tw", "gaa", "ee", "dag", "yo", "ig", "sw", "ki", "luo", "suk"];
365
+ readonly afroasiatic: readonly ["ha", "ar"];
366
+ readonly indo_european: readonly ["en", "fr", "es", "pt", "hi", "bn", "mr"];
367
+ readonly quechuan: readonly ["qu"];
368
+ readonly aymaran: readonly ["ay"];
369
+ readonly sino_tibetan: readonly ["zh"];
370
+ readonly dravidian: readonly ["ta", "te"];
371
+ readonly tupian: readonly ["gn"];
372
+ };
373
+
374
+ export { CulturalContext, type CulturalContextConfig, type DetectionResult, type I18nOptions, LANGUAGE_FAMILIES, type LanguageConfig, SUPPORTED_LANGUAGES, type TranslateOptions, type TranslationCatalog, type TranslationEntry, type TranslationMap, type TranslatorOptions, createTranslator, formatCurrency, formatI18nDate, formatNumber, formatRelativeTime, getCulturalContext, getDirection, isRTL };