source dump of claude code
at main 94 lines 2.8 kB view raw
1/** 2 * Shared Intl object instances with lazy initialization. 3 * 4 * Intl constructors are expensive (~0.05-0.1ms each), so we cache instances 5 * for reuse across the codebase instead of creating new ones each time. 6 * Lazy initialization ensures we only pay the cost when actually needed. 7 */ 8 9// Segmenters for Unicode text processing (lazily initialized) 10let graphemeSegmenter: Intl.Segmenter | null = null 11let wordSegmenter: Intl.Segmenter | null = null 12 13export function getGraphemeSegmenter(): Intl.Segmenter { 14 if (!graphemeSegmenter) { 15 graphemeSegmenter = new Intl.Segmenter(undefined, { 16 granularity: 'grapheme', 17 }) 18 } 19 return graphemeSegmenter 20} 21 22/** 23 * Extract the first grapheme cluster from a string. 24 * Returns '' for empty strings. 25 */ 26export function firstGrapheme(text: string): string { 27 if (!text) return '' 28 const segments = getGraphemeSegmenter().segment(text) 29 const first = segments[Symbol.iterator]().next().value 30 return first?.segment ?? '' 31} 32 33/** 34 * Extract the last grapheme cluster from a string. 35 * Returns '' for empty strings. 36 */ 37export function lastGrapheme(text: string): string { 38 if (!text) return '' 39 let last = '' 40 for (const { segment } of getGraphemeSegmenter().segment(text)) { 41 last = segment 42 } 43 return last 44} 45 46export function getWordSegmenter(): Intl.Segmenter { 47 if (!wordSegmenter) { 48 wordSegmenter = new Intl.Segmenter(undefined, { granularity: 'word' }) 49 } 50 return wordSegmenter 51} 52 53// RelativeTimeFormat cache (keyed by style:numeric) 54const rtfCache = new Map<string, Intl.RelativeTimeFormat>() 55 56export function getRelativeTimeFormat( 57 style: 'long' | 'short' | 'narrow', 58 numeric: 'always' | 'auto', 59): Intl.RelativeTimeFormat { 60 const key = `${style}:${numeric}` 61 let rtf = rtfCache.get(key) 62 if (!rtf) { 63 rtf = new Intl.RelativeTimeFormat('en', { style, numeric }) 64 rtfCache.set(key, rtf) 65 } 66 return rtf 67} 68 69// Timezone is constant for the process lifetime 70let cachedTimeZone: string | null = null 71 72export function getTimeZone(): string { 73 if (!cachedTimeZone) { 74 cachedTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone 75 } 76 return cachedTimeZone 77} 78 79// System locale language subtag (e.g. 'en', 'ja') is constant for the process 80// lifetime. null = not yet computed; undefined = computed but unavailable (so 81// a stripped-ICU environment fails once instead of retrying on every call). 82let cachedSystemLocaleLanguage: string | undefined | null = null 83 84export function getSystemLocaleLanguage(): string | undefined { 85 if (cachedSystemLocaleLanguage === null) { 86 try { 87 const locale = Intl.DateTimeFormat().resolvedOptions().locale 88 cachedSystemLocaleLanguage = new Intl.Locale(locale).language 89 } catch { 90 cachedSystemLocaleLanguage = undefined 91 } 92 } 93 return cachedSystemLocaleLanguage 94}