using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Media; using PCL.Core.App.IoC; namespace PCL.Core.App.Localization; /// /// 启动器 UI 字体服务。 /// public static class LocalizationFontService { private const string PclEnglishFont = "./Resources/#PCL English"; private static readonly Uri _ApplicationPackUri = new("pack://application:,,,/"); private static readonly IReadOnlyDictionary _ExactCultureProfiles = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["zh-CN"] = LocalizationFontProfile.SimplifiedChinese, ["zh-SG"] = LocalizationFontProfile.SimplifiedChinese, ["zh-TW"] = LocalizationFontProfile.TraditionalChinese, ["zh-HK"] = LocalizationFontProfile.TraditionalChinese, ["zh-MO"] = LocalizationFontProfile.TraditionalChinese }; private static readonly IReadOnlyDictionary _ScriptProfiles = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["Hans"] = LocalizationFontProfile.SimplifiedChinese, ["Hant"] = LocalizationFontProfile.TraditionalChinese }; private static readonly IReadOnlyDictionary _LanguageProfiles = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["zh"] = LocalizationFontProfile.SimplifiedChinese, ["ja"] = LocalizationFontProfile.Japanese, ["ko"] = LocalizationFontProfile.Korean, ["en"] = LocalizationFontProfile.English }; /// /// 生成启动器 UI 使用的 FontFamily。 /// /// 用户自定义字体。为空时使用当前语言默认字体链。 /// 目标语言。为空时使用当前 UI 语言。 public static FontFamily BuildLaunchFontFamily(string? customFontName = null, LocalizationLanguage? language = null) { language ??= LocalizationService.CurrentLanguage; var familyNames = string.IsNullOrWhiteSpace(customFontName) ? _GetDefaultFamilyNames(language.FontProfile) : _GetCustomFamilyNames(customFontName, language.FontProfile); return new FontFamily(_ApplicationPackUri, string.Join(", ", familyNames)); } /// /// 生成用于代表某种语言的 FontFamily。 /// public static FontFamily BuildRepresentativeFontFamily(LocalizationLanguage language) { return BuildRepresentativeFontFamily(language.FontProfile); } /// /// 生成用于代表某种字体策略的 FontFamily。 /// public static FontFamily BuildRepresentativeFontFamily(LocalizationFontProfile profile) { return new FontFamily(_ApplicationPackUri, string.Join(", ", _GetDefaultFamilyNames(profile))); } /// /// 应用启动器 UI 字体。 /// public static void ApplyLaunchFont(string? customFontName = null, LocalizationLanguage? language = null) { var app = Application.Current ?? Lifecycle.CurrentApplication; var fontFamily = BuildLaunchFontFamily(customFontName, language); if (!app.Dispatcher.CheckAccess()) { app.Dispatcher.Invoke(() => app.Resources["LaunchFontFamily"] = fontFamily); return; } app.Resources["LaunchFontFamily"] = fontFamily; } /// /// 根据区域性名称解析字体策略。 /// public static LocalizationFontProfile ResolveProfileFromCultureName(string? cultureName) { var code = _NormalizeCultureCode(cultureName); if (string.IsNullOrEmpty(code)) return LocalizationFontProfile.Other; if (_ExactCultureProfiles.TryGetValue(code, out var exactProfile)) return exactProfile; var cultureParts = code.Split('-', StringSplitOptions.RemoveEmptyEntries); foreach (var part in cultureParts.Skip(1)) if (_ScriptProfiles.TryGetValue(part, out var scriptProfile)) return scriptProfile; var languageCode = cultureParts.FirstOrDefault(); return languageCode is not null && _LanguageProfiles.TryGetValue(languageCode, out var languageProfile) ? languageProfile : LocalizationFontProfile.Other; } private static string _NormalizeCultureCode(string? value) { return string.IsNullOrWhiteSpace(value) ? string.Empty : value.Replace('_', '-').Trim(); } private static IReadOnlyList _GetDefaultFamilyNames(LocalizationFontProfile profile) { return profile switch { LocalizationFontProfile.English => [PclEnglishFont, "Segoe UI", "Microsoft YaHei UI"], LocalizationFontProfile.SimplifiedChinese => [PclEnglishFont, "Microsoft YaHei UI", "Segoe UI"], LocalizationFontProfile.TraditionalChinese => [PclEnglishFont, "Microsoft JhengHei UI", "Microsoft YaHei UI", "Segoe UI"], LocalizationFontProfile.Japanese => [PclEnglishFont, "Yu Gothic UI", "Microsoft YaHei UI", "Segoe UI"], LocalizationFontProfile.Korean => [PclEnglishFont, "Malgun Gothic", "Microsoft YaHei UI", "Segoe UI"], _ => ["Segoe UI", "Microsoft YaHei UI"] }; } private static IReadOnlyList _GetCustomFamilyNames(string customFontName, LocalizationFontProfile profile) { var familyNames = _GetDefaultFamilyNames(profile) .Where(name => !string.Equals(name, PclEnglishFont, StringComparison.OrdinalIgnoreCase)) .ToList(); familyNames.Insert(0, _EscapeFontFamilyName(customFontName)); return familyNames.Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); } private static string _EscapeFontFamilyName(string name) { return name.Replace(",", ",,"); } }