Skip to content
44 changes: 44 additions & 0 deletions config/i18n-scripts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"languageConfig": {
"ar": {
"direction": "rtl",
"script": "arabic",
"fontFamily": "'Noto Naskh Arabic', 'Arabic UI', system-ui, -apple-system"
},
"bn": {
"direction": "ltr",
"script": "bengali",
"fontFamily": "'Noto Sans Bengali', 'Bangla Sangam MN', system-ui, -apple-system"
},
"fa": {
"direction": "rtl",
"script": "arabic",
"fontFamily": "'Noto Naskh Arabic', 'Arabic UI', system-ui, -apple-system"
},
"he": {
"direction": "rtl",
"script": "hebrew",
"fontFamily": "'Noto Sans Hebrew', 'Hebrew UI', system-ui, -apple-system"
},
"hi": {
"direction": "ltr",
"script": "devanagari",
"fontFamily": "'Noto Sans Devanagari', 'Devanagari Sangam MN', system-ui, -apple-system"
},
"mr": {
"direction": "ltr",
"script": "devanagari",
"fontFamily": "'Noto Sans Devanagari', 'Devanagari Sangam MN', system-ui, -apple-system"
},
"ne": {
"direction": "ltr",
"script": "devanagari",
"fontFamily": "'Noto Sans Devanagari', 'Devanagari Sangam MN', system-ui, -apple-system"
},
"si": {
"direction": "ltr",
"script": "sinhala",
"fontFamily": "'Noto Sans Sinhala', 'Sinhala Sangam MN', system-ui, -apple-system"
}
}
}
116 changes: 99 additions & 17 deletions i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,106 @@
"version": "1.10",
"locale": {
"source": "en",
"config": {
"direction": "ltr",
"script": "latin"
},
"targets": [
"ru",
"he",
"fr",
"es",
"de",
"zh-Hans",
"ko",
"ja",
"it",
"ar",
"hi",
"pt-BR",
"uk-UA",
"bn",
"fa",
"pl",
"tr"
{
"code": "ar",
"direction": "rtl",
"script": "arabic"
},
{
"code": "bn",
"direction": "ltr",
"script": "bengali"
},
{
"code": "de",
"direction": "ltr",
"script": "latin"
},
{
"code": "es",
"direction": "ltr",
"script": "latin"
},
{
"code": "fa",
"direction": "rtl",
"script": "arabic"
},
{
"code": "fr",
"direction": "ltr",
"script": "latin"
},
{
"code": "he",
"direction": "rtl",
"script": "hebrew"
},
{
"code": "hi",
"direction": "ltr",
"script": "devanagari"
},
{
"code": "it",
"direction": "ltr",
"script": "latin"
},
{
"code": "ja",
"direction": "ltr",
"script": "japanese"
},
{
"code": "ko",
"direction": "ltr",
"script": "hangul"
},
{
"code": "mr",
"direction": "ltr",
"script": "devanagari"
},
{
"code": "ne",
"direction": "ltr",
"script": "devanagari"
},
{
"code": "pl",
"direction": "ltr",
"script": "latin"
},
{
"code": "pt-BR",
"direction": "ltr",
"script": "latin"
},
{
"code": "ru",
"direction": "ltr",
"script": "cyrillic"
},
{
"code": "tr",
"direction": "ltr",
"script": "latin"
},
{
"code": "uk-UA",
"direction": "ltr",
"script": "cyrillic"
},
{
"code": "zh-Hans",
"direction": "ltr",
"script": "hans"
}
]
},
"buckets": {
Expand Down
38 changes: 38 additions & 0 deletions packages/sdk/src/components/LocalizedText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import { useScriptStyle } from '../hooks/useScriptStyle';

interface LocalizedTextProps {
locale: string;
children: React.ReactNode;
className?: string;
style?: React.CSSProperties;
}

export function LocalizedText({ locale, children, className = '', style = {} }: LocalizedTextProps) {
const { style: scriptStyle } = useScriptStyle(locale);

return (
<div className={className} style={{ ...scriptStyle, ...style }}>
{children}
</div>
);
}

interface LocalizedContentProps {
locale: string;
html: string;
className?: string;
style?: React.CSSProperties;
}

export function LocalizedContent({ locale, html, className = '', style = {} }: LocalizedContentProps) {
const { style: scriptStyle } = useScriptStyle(locale);

return (
<div
className={className}
style={{ ...scriptStyle, ...style }}
dangerouslySetInnerHTML={{ __html: html }}
/>
);
}
23 changes: 23 additions & 0 deletions packages/sdk/src/hooks/useScriptStyle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useMemo } from 'react';
import { getScriptConfig, getScriptStyle } from '../utils/scriptConfig';

export function useScriptStyle(locale: string) {
return useMemo(() => {
const config = getScriptConfig(locale);
const style = getScriptStyle(locale);

return {
config,
style,
isRTL: config?.direction === 'rtl',
hasSpecialScript: Boolean(config?.script && config.script !== 'latin'),
};
}, [locale]);
}

export function useScriptDirection(locale: string) {
return useMemo(() => {
const config = getScriptConfig(locale);
return config?.direction || 'ltr';
}, [locale]);
}
54 changes: 54 additions & 0 deletions packages/sdk/src/utils/scriptConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { readFileSync } from 'fs';
import { join } from 'path';

interface ScriptConfig {
direction: 'ltr' | 'rtl';
script: string;
fontFamily: string;
}

interface I18nScriptConfig {
languageConfig: {
[key: string]: ScriptConfig;
}
}

export function getScriptConfig(locale: string): ScriptConfig | null {
try {
const configPath = join(__dirname, '../config/i18n-scripts.json');
const config = JSON.parse(readFileSync(configPath, 'utf8')) as I18nScriptConfig;
return config.languageConfig[locale] || null;
} catch (error) {
console.error('Error loading script configuration:', error);
return null;
}
}

export function getDirectionClass(locale: string): string {
const config = getScriptConfig(locale);
return config?.direction || 'ltr';
}

export function getScriptStyle(locale: string): { [key: string]: string } {
const config = getScriptConfig(locale);
if (!config) return {};

return {
direction: config.direction,
fontFamily: config.fontFamily,
...(config.direction === 'rtl' && {
textAlign: 'right',
}),
};
}

export function wrapWithScriptStyle(content: string, locale: string): string {
const config = getScriptConfig(locale);
if (!config) return content;

const style = `direction: ${config.direction}; font-family: ${config.fontFamily}; ${
config.direction === 'rtl' ? 'text-align: right;' : ''
}`;

return `<div style="${style}">${content}</div>`;
}
Loading
Loading