149 lines
4.5 KiB
TypeScript
149 lines
4.5 KiB
TypeScript
type Language = 'zh-CN' | 'zh-TW' | 'en-US' | 'ja-JP' | 'ko-KR'
|
|
|
|
interface FontConfig {
|
|
name: string
|
|
file: string
|
|
unicodeRange?: string
|
|
}
|
|
|
|
const fontConfigs: Record<Language, FontConfig[]> = {
|
|
'zh-CN': [
|
|
{
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-sc-regular.woff2',
|
|
unicodeRange: 'U+4E00-9FFF, U+3400-4DBF, U+20000-2A6DF, U+2A700-2B73F, U+2B740-2B81F, U+2B820-2CEAF, U+F900-FAFF, U+2F800-2FA1F',
|
|
},
|
|
{
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-latin-regular.woff2',
|
|
unicodeRange: 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD',
|
|
},
|
|
],
|
|
'zh-TW': [
|
|
{
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-tc-regular.woff2',
|
|
unicodeRange: 'U+4E00-9FFF, U+3400-4DBF, U+F900-FAFF',
|
|
},
|
|
{
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-sc-regular.woff2',
|
|
unicodeRange: 'U+20000-2A6DF, U+2A700-2B73F, U+2B740-2B81F, U+2B820-2CEAF, U+2F800-2FA1F',
|
|
},
|
|
{
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-latin-regular.woff2',
|
|
unicodeRange: 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD',
|
|
},
|
|
],
|
|
'en-US': [
|
|
{
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-latin-regular.woff2',
|
|
unicodeRange: 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD',
|
|
},
|
|
],
|
|
'ja-JP': [
|
|
{
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-jp-regular.woff2',
|
|
unicodeRange: 'U+3000-30FF, U+4E00-9FFF, U+FF00-FFEF',
|
|
},
|
|
{
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-latin-regular.woff2',
|
|
unicodeRange: 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD',
|
|
},
|
|
],
|
|
'ko-KR': [
|
|
{
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-kr-regular.woff2',
|
|
unicodeRange: 'U+AC00-D7AF, U+1100-11FF, U+3130-318F',
|
|
},
|
|
{
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-latin-regular.woff2',
|
|
unicodeRange: 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD',
|
|
},
|
|
],
|
|
}
|
|
|
|
const loadedFonts = new Set<string>()
|
|
|
|
function createFontFace(config: FontConfig): FontFace {
|
|
const descriptors: FontFaceDescriptors = {
|
|
style: 'normal',
|
|
weight: '400',
|
|
display: 'swap',
|
|
}
|
|
|
|
if (config.unicodeRange) {
|
|
descriptors.unicodeRange = config.unicodeRange
|
|
}
|
|
|
|
return new FontFace(config.name, `url(${config.file}) format('woff2')`, descriptors)
|
|
}
|
|
|
|
export function loadFontsForLanguage(language: Language): void {
|
|
const configs = fontConfigs[language]
|
|
if (!configs) return
|
|
|
|
configs.forEach((config) => {
|
|
const fontKey = `${config.name}-${config.file}`
|
|
|
|
if (loadedFonts.has(fontKey)) {
|
|
return
|
|
}
|
|
|
|
try {
|
|
const fontFace = createFontFace(config)
|
|
document.fonts.add(fontFace)
|
|
loadedFonts.add(fontKey)
|
|
} catch (error) {
|
|
console.warn(`Failed to register font ${config.file}:`, error)
|
|
}
|
|
})
|
|
}
|
|
|
|
export function detectBrowserLanguage(): Language {
|
|
const browserLang = navigator.language.toLowerCase()
|
|
|
|
if (browserLang.startsWith('zh-tw') || browserLang.startsWith('zh-hk') || browserLang.startsWith('zh-mo')) {
|
|
return 'zh-TW'
|
|
}
|
|
if (browserLang.startsWith('zh')) {
|
|
return 'zh-CN'
|
|
}
|
|
if (browserLang.startsWith('ja')) {
|
|
return 'ja-JP'
|
|
}
|
|
if (browserLang.startsWith('ko')) {
|
|
return 'ko-KR'
|
|
}
|
|
|
|
return 'en-US'
|
|
}
|
|
|
|
export function preloadBaseFont(): void {
|
|
const baseConfig: FontConfig = {
|
|
name: 'Noto Serif',
|
|
file: '/fonts/noto-serif-latin-regular.woff2',
|
|
unicodeRange: 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD',
|
|
}
|
|
|
|
const fontKey = `${baseConfig.name}-${baseConfig.file}`
|
|
|
|
if (loadedFonts.has(fontKey)) {
|
|
return
|
|
}
|
|
|
|
try {
|
|
const fontFace = createFontFace(baseConfig)
|
|
document.fonts.add(fontFace)
|
|
loadedFonts.add(fontKey)
|
|
} catch (error) {
|
|
console.warn('Failed to register base font:', error)
|
|
}
|
|
}
|