Typography 2026 Language Learning | Skills Pool
Typography 2026 Language Learning Typography optimized for multi-language apps and language learning platforms. Features Noto Sans for 42+ languages, clear character distinction, and pronunciation-friendly spacing.
FutureAtoms 0 스타 2026. 3. 11. Language Learning Typography 2026
Typography specifically designed for multi-language apps, language learning platforms, and global applications supporting 42+ languages.
Design Requirements for Language Learning
Multi-Script Support - Latin, Cyrillic, CJK, Arabic, Hebrew, Devanagari, etc.
Character Distinction - Clear differentiation between similar characters
Pronunciation Markers - Space for diacritics, tone marks, phonetic guides
Readability at All Sizes - Vocabulary cards to reading passages
Consistent Vertical Rhythm - Across mixed-language content
Featured Font Families
Universal Multi-Language
빠른 설치
Typography 2026 Language Learning npx skills add FutureAtoms/claude-skills-backup
스타 0
업데이트 2026. 3. 11.
직업 Noto Sans 150+ 1000+ Free (Google) Noto Serif 100+ 800+ Free (Google) Source Han Sans CJK + Latin Chinese, Japanese, Korean Free (Adobe) Inter Latin, Cyrillic, Greek 200+ Free
Script-Specific Excellence Script Recommended Font Notes Latin Inter, Source Sans Best for European languages Cyrillic Inter, Source Sans Russian, Ukrainian, etc. CJK Noto Sans CJK, Source Han Chinese, Japanese, Korean Arabic Noto Naskh Arabic Right-to-left support Hebrew Noto Sans Hebrew Right-to-left support Devanagari Noto Sans Devanagari Hindi, Sanskrit, Marathi Thai Noto Sans Thai Tone mark support
Learner-Friendly Options Font Best For Why Nunito Beginners Rounded, friendly Quicksand Vocabulary Clear, geometric Open Sans Reading Highly readable Lexie Readable Dyslexic learners Designed for accessibility
Leviosa Language Support Based on Gemini 2.5 Flash Native support (42+ languages):
Tier 1 Languages (Native Audio) English, Spanish, French, German, Italian, Portuguese,
Dutch, Russian, Japanese, Korean, Mandarin Chinese,
Hindi, Arabic, Turkish, Polish, Swedish, Norwegian,
Danish, Finnish, Czech, Greek, Romanian, Hungarian,
Vietnamese, Thai, Indonesian
Font Strategy for Leviosa // Primary: Noto Sans for universal support
// Fallback: System fonts for platform optimization
// Accent: Nunito for playful UI elements
React Native Implementation
1. Install Dependencies npx expo install expo-font \
@expo-google-fonts/noto-sans \
@expo-google-fonts/nunito \
@expo-google-fonts/inter
2. Multi-Language Font Loading // apps/mobile/app/_layout.tsx
import { useFonts } from 'expo-font';
import {
NotoSans_400Regular,
NotoSans_500Medium,
NotoSans_600SemiBold,
NotoSans_700Bold,
NotoSans_400Regular_Italic,
} from '@expo-google-fonts/noto-sans';
import {
Nunito_400Regular,
Nunito_500Medium,
Nunito_600SemiBold,
Nunito_700Bold,
} from '@expo-google-fonts/nunito';
export default function RootLayout() {
const [fontsLoaded] = useFonts({
// Noto Sans (multi-language)
'NotoSans-Regular': NotoSans_400Regular,
'NotoSans-Medium': NotoSans_500Medium,
'NotoSans-SemiBold': NotoSans_600SemiBold,
'NotoSans-Bold': NotoSans_700Bold,
'NotoSans-Italic': NotoSans_400Regular_Italic,
// Nunito (UI, playful elements)
'Nunito-Regular': Nunito_400Regular,
'Nunito-Medium': Nunito_500Medium,
'Nunito-SemiBold': Nunito_600SemiBold,
'Nunito-Bold': Nunito_700Bold,
// CJK fonts (download from Google Fonts)
// These are large files, consider on-demand loading
// 'NotoSansCJK-Regular': require('../assets/fonts/NotoSansCJK-Regular.otf'),
// Arabic (RTL)
// 'NotoNaskhArabic-Regular': require('../assets/fonts/NotoNaskhArabic-Regular.ttf'),
});
// ... splash screen handling
}
3. On-Demand Font Loading for Large Scripts // packages/data/src/hooks/useLanguageFont.ts
import { useFonts } from 'expo-font';
import { useMemo } from 'react';
type ScriptFamily = 'latin' | 'cjk' | 'arabic' | 'devanagari' | 'cyrillic' | 'thai';
const SCRIPT_FONTS: Record<ScriptFamily, Record<string, any>> = {
latin: {
'NotoSans-Regular': require('../../assets/fonts/NotoSans-Regular.ttf'),
'NotoSans-Bold': require('../../assets/fonts/NotoSans-Bold.ttf'),
},
cjk: {
'NotoSansCJK-Regular': require('../../assets/fonts/NotoSansCJK-Regular.otf'),
'NotoSansCJK-Bold': require('../../assets/fonts/NotoSansCJK-Bold.otf'),
},
arabic: {
'NotoNaskhArabic-Regular': require('../../assets/fonts/NotoNaskhArabic-Regular.ttf'),
'NotoNaskhArabic-Bold': require('../../assets/fonts/NotoNaskhArabic-Bold.ttf'),
},
devanagari: {
'NotoSansDevanagari-Regular': require('../../assets/fonts/NotoSansDevanagari-Regular.ttf'),
'NotoSansDevanagari-Bold': require('../../assets/fonts/NotoSansDevanagari-Bold.ttf'),
},
cyrillic: {
'NotoSans-Regular': require('../../assets/fonts/NotoSans-Regular.ttf'),
'NotoSans-Bold': require('../../assets/fonts/NotoSans-Bold.ttf'),
},
thai: {
'NotoSansThai-Regular': require('../../assets/fonts/NotoSansThai-Regular.ttf'),
'NotoSansThai-Bold': require('../../assets/fonts/NotoSansThai-Bold.ttf'),
},
};
export function useLanguageFont(targetLanguage: string) {
const scriptFamily = useMemo(() => getScriptFamily(targetLanguage), [targetLanguage]);
const [fontsLoaded] = useFonts(SCRIPT_FONTS[scriptFamily]);
return {
fontsLoaded,
fontFamily: getFontFamily(scriptFamily),
};
}
function getScriptFamily(language: string): ScriptFamily {
const cjkLanguages = ['zh', 'ja', 'ko', 'chinese', 'japanese', 'korean'];
const arabicLanguages = ['ar', 'arabic', 'fa', 'persian', 'ur', 'urdu'];
const devanagariLanguages = ['hi', 'hindi', 'mr', 'marathi', 'sa', 'sanskrit'];
const cyrillicLanguages = ['ru', 'russian', 'uk', 'ukrainian', 'bg', 'bulgarian'];
const thaiLanguages = ['th', 'thai'];
const lang = language.toLowerCase();
if (cjkLanguages.some(l => lang.includes(l))) return 'cjk';
if (arabicLanguages.some(l => lang.includes(l))) return 'arabic';
if (devanagariLanguages.some(l => lang.includes(l))) return 'devanagari';
if (cyrillicLanguages.some(l => lang.includes(l))) return 'cyrillic';
if (thaiLanguages.some(l => lang.includes(l))) return 'thai';
return 'latin';
}
function getFontFamily(script: ScriptFamily): { regular: string; bold: string } {
const families: Record<ScriptFamily, { regular: string; bold: string }> = {
latin: { regular: 'NotoSans-Regular', bold: 'NotoSans-Bold' },
cjk: { regular: 'NotoSansCJK-Regular', bold: 'NotoSansCJK-Bold' },
arabic: { regular: 'NotoNaskhArabic-Regular', bold: 'NotoNaskhArabic-Bold' },
devanagari: { regular: 'NotoSansDevanagari-Regular', bold: 'NotoSansDevanagari-Bold' },
cyrillic: { regular: 'NotoSans-Regular', bold: 'NotoSans-Bold' },
thai: { regular: 'NotoSansThai-Regular', bold: 'NotoSansThai-Bold' },
};
return families[script];
}
Design Tokens // packages/ui/src/tokens/typography-language.ts
import { I18nManager, Platform } from 'react-native';
export const languageLearningTypography = {
fonts: {
// Primary content (multi-language)
content: 'NotoSans-Regular',
contentMedium: 'NotoSans-Medium',
contentBold: 'NotoSans-Bold',
contentItalic: 'NotoSans-Italic',
// UI elements (playful)
ui: 'Nunito-Regular',
uiMedium: 'Nunito-Medium',
uiBold: 'Nunito-Bold',
// Fallback
system: Platform.select({
ios: 'System',
android: 'Roboto',
default: 'sans-serif',
}),
},
sizes: {
// Vocabulary - large, clear
vocabularyWord: {
fontSize: 32,
lineHeight: 44,
letterSpacing: 0.5,
},
vocabularyTranslation: {
fontSize: 20,
lineHeight: 28,
letterSpacing: 0.3,
},
vocabularyExample: {
fontSize: 16,
lineHeight: 26,
letterSpacing: 0.2,
},
// Reading passages
readingTitle: {
fontSize: 24,
lineHeight: 32,
letterSpacing: 0,
},
readingBody: {
fontSize: 18,
lineHeight: 32, // Extra line height for annotations
letterSpacing: 0.3,
},
readingCaption: {
fontSize: 14,
lineHeight: 20,
letterSpacing: 0.2,
},
// Pronunciation guides
phonetic: {
fontSize: 16,
lineHeight: 24,
letterSpacing: 0.5,
},
romanization: {
fontSize: 14,
lineHeight: 20,
letterSpacing: 0.3,
},
// UI elements
buttonLabel: {
fontSize: 16,
lineHeight: 20,
letterSpacing: 0.3,
},
navLabel: {
fontSize: 12,
lineHeight: 16,
letterSpacing: 0.2,
},
// XP and gamification
xpValue: {
fontSize: 24,
lineHeight: 28,
letterSpacing: 0,
},
streakCount: {
fontSize: 32,
lineHeight: 36,
letterSpacing: 0,
},
},
// RTL support
rtl: {
isRTL: I18nManager.isRTL,
textAlign: I18nManager.isRTL ? 'right' : 'left',
writingDirection: I18nManager.isRTL ? 'rtl' : 'ltr',
},
// CJK-specific adjustments
cjk: {
// CJK characters need more line height
lineHeightMultiplier: 1.8,
// No letter spacing for CJK
letterSpacing: 0,
// Word spacing handled differently
wordSpacing: 0,
},
// Arabic-specific adjustments
arabic: {
lineHeightMultiplier: 1.7,
letterSpacing: 0,
// Kashida (elongation) support
textJustify: 'kashida',
},
};
Component Examples
Vocabulary Card Component // packages/ui/src/components/VocabularyCard.tsx
import { View, StyleSheet, Pressable } from 'react-native';
import { Text } from 'react-native';
import { languageLearningTypography as t } from '../tokens/typography-language';
import { useLanguageFont } from '../hooks/useLanguageFont';
interface VocabularyCardProps {
word: string;
translation: string;
phonetic?: string;
example?: string;
targetLanguage: string;
onPress?: () => void;
}
export function VocabularyCard({
word,
translation,
phonetic,
example,
targetLanguage,
onPress
}: VocabularyCardProps) {
const { fontFamily } = useLanguageFont(targetLanguage);
return (
<Pressable onPress={onPress} style={styles.card}>
{/* Target language word */}
<Text
style={[
styles.word,
{ fontFamily: fontFamily.bold }
]}
>
{word}
</Text>
{/* Phonetic pronunciation */}
{phonetic && (
<Text style={styles.phonetic}>
/{phonetic}/
</Text>
)}
{/* Native language translation */}
<Text style={styles.translation}>
{translation}
</Text>
{/* Example sentence */}
{example && (
<Text
style={[
styles.example,
{ fontFamily: fontFamily.regular }
]}
>
{example}
</Text>
)}
</Pressable>
);
}
const styles = StyleSheet.create({
card: {
backgroundColor: '#ffffff',
borderRadius: 16,
padding: 20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 8,
elevation: 3,
},
word: {
...t.sizes.vocabularyWord,
color: '#1a1a1a',
marginBottom: 4,
},
phonetic: {
fontFamily: 'NotoSans-Regular',
...t.sizes.phonetic,
color: '#6b7280',
marginBottom: 12,
},
translation: {
fontFamily: 'Nunito-SemiBold',
...t.sizes.vocabularyTranslation,
color: '#4b5563',
marginBottom: 8,
},
example: {
...t.sizes.vocabularyExample,
color: '#6b7280',
fontStyle: 'italic',
},
});
Multi-Language Text Component // packages/ui/src/components/LanguageText.tsx
import { Text as RNText, TextStyle, I18nManager } from 'react-native';
import { useLanguageFont } from '../hooks/useLanguageFont';
import { languageLearningTypography as t } from '../tokens/typography-language';
interface LanguageTextProps {
children: string;
language: string;
variant?: 'word' | 'sentence' | 'paragraph';
showPhonetic?: boolean;
phoneticText?: string;
style?: TextStyle;
}
export function LanguageText({
children,
language,
variant = 'sentence',
showPhonetic = false,
phoneticText,
style
}: LanguageTextProps) {
const { fontFamily } = useLanguageFont(language);
const isRTL = isRTLLanguage(language);
const variantStyles: Record<string, TextStyle> = {
word: t.sizes.vocabularyWord,
sentence: t.sizes.readingBody,
paragraph: t.sizes.readingBody,
};
return (
<>
<RNText
style={[
variantStyles[variant],
{
fontFamily: fontFamily.regular,
writingDirection: isRTL ? 'rtl' : 'ltr',
textAlign: isRTL ? 'right' : 'left',
},
style
]}
>
{children}
</RNText>
{showPhonetic && phoneticText && (
<RNText style={styles.phonetic}>
[{phoneticText}]
</RNText>
)}
</>
);
}
function isRTLLanguage(language: string): boolean {
const rtlLanguages = ['ar', 'arabic', 'he', 'hebrew', 'fa', 'persian', 'ur', 'urdu'];
return rtlLanguages.some(l => language.toLowerCase().includes(l));
}
const styles = {
phonetic: {
fontFamily: 'NotoSans-Regular',
fontSize: 14,
color: '#6b7280',
marginTop: 4,
},
};
Reading Passage Component // packages/ui/src/components/ReadingPassage.tsx
import { View, Text, StyleSheet, ScrollView } from 'react-native';
import { useLanguageFont } from '../hooks/useLanguageFont';
import { languageLearningTypography as t } from '../tokens/typography-language';
interface ReadingPassageProps {
title: string;
content: string;
language: string;
level?: 'A1' | 'A2' | 'B1' | 'B2' | 'C1' | 'C2';
annotations?: Array<{
start: number;
end: number;
note: string;
}>;
}
export function ReadingPassage({
title,
content,
language,
level,
annotations = []
}: ReadingPassageProps) {
const { fontFamily } = useLanguageFont(language);
const isRTL = isRTLLanguage(language);
return (
<ScrollView style={styles.container}>
{/* Level badge */}
{level && (
<View style={styles.levelBadge}>
<Text style={styles.levelText}>{level}</Text>
</View>
)}
{/* Title */}
<Text
style={[
styles.title,
{
fontFamily: fontFamily.bold,
textAlign: isRTL ? 'right' : 'left',
}
]}
>
{title}
</Text>
{/* Content */}
<Text
style={[
styles.content,
{
fontFamily: fontFamily.regular,
writingDirection: isRTL ? 'rtl' : 'ltr',
textAlign: isRTL ? 'right' : 'left',
}
]}
>
{content}
</Text>
</ScrollView>
);
}
function isRTLLanguage(language: string): boolean {
const rtlLanguages = ['ar', 'arabic', 'he', 'hebrew', 'fa', 'persian', 'ur', 'urdu'];
return rtlLanguages.some(l => language.toLowerCase().includes(l));
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#FFFDF9',
},
levelBadge: {
alignSelf: 'flex-start',
backgroundColor: '#E0F4FF',
paddingHorizontal: 12,
paddingVertical: 6,
borderRadius: 8,
marginBottom: 16,
},
levelText: {
fontFamily: 'Nunito-Bold',
fontSize: 12,
color: '#3D5A80',
letterSpacing: 1,
},
title: {
...t.sizes.readingTitle,
color: '#1a1a1a',
marginBottom: 20,
},
content: {
...t.sizes.readingBody,
color: '#374151',
},
});
Font File Size Optimization // Noto Sans file sizes (approximate)
const fontSizes = {
'NotoSans-Regular.ttf': '~400KB', // Latin + common
'NotoSansCJK-Regular.otf': '~15MB', // CJK is huge
'NotoNaskhArabic-Regular.ttf': '~150KB', // Arabic
'NotoSansDevanagari-Regular.ttf': '~100KB',
'NotoSansThai-Regular.ttf': '~80KB',
};
// Strategy: Load base fonts at startup, load CJK on-demand
// Consider using Google Fonts CDN for web
Font Sources
Language Learning App Examples App Font Strategy Notes Duolingo Custom + Noto Script-specific loading Babbel Open Sans + Noto Consistent UI Rosetta Stone Proprietary Full script support Drops Rounded sans Playful, gamified HelloTalk System + Noto Message-focused
02
Design Requirements for Language Learning
IDE 플러그인
Agent Customization **WORKFLOW SKILL** — Create, update, review, fix, or debug VS Code agent customization files (.instructions.md, .prompt.md, .agent.md, SKILL.md, copilot-instructions.md, AGENTS.md). USE FOR: saving coding preferences; troubleshooting why instructions/skills/agents are ignored or not invoked; configuring applyTo patterns; defining tool restrictions; creating custom agent modes or specialized workflows; packaging domain knowledge; fixing YAML frontmatter syntax. DO NOT USE FOR: general coding questions (use default agent); runtime debugging or error diagnosis; MCP server configuration (use MCP docs directly); VS Code extension development. INVOKES: file system tools (read/write customization files), ask-questions tool (interview user for requirements), subagents for codebase exploration. FOR SINGLE OPERATIONS: For quick YAML frontmatter fixes or creating a single file from a known pattern, edit the file directly — no skill needed.