初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 启动器 UI 字体服务。
|
||||
/// </summary>
|
||||
public static class LocalizationFontService
|
||||
{
|
||||
private const string PclEnglishFont = "./Resources/#PCL English";
|
||||
private static readonly Uri _ApplicationPackUri = new("pack://application:,,,/");
|
||||
|
||||
private static readonly IReadOnlyDictionary<string, LocalizationFontProfile> _ExactCultureProfiles =
|
||||
new Dictionary<string, LocalizationFontProfile>(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<string, LocalizationFontProfile> _ScriptProfiles =
|
||||
new Dictionary<string, LocalizationFontProfile>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["Hans"] = LocalizationFontProfile.SimplifiedChinese,
|
||||
["Hant"] = LocalizationFontProfile.TraditionalChinese
|
||||
};
|
||||
|
||||
private static readonly IReadOnlyDictionary<string, LocalizationFontProfile> _LanguageProfiles =
|
||||
new Dictionary<string, LocalizationFontProfile>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["zh"] = LocalizationFontProfile.SimplifiedChinese,
|
||||
["ja"] = LocalizationFontProfile.Japanese,
|
||||
["ko"] = LocalizationFontProfile.Korean,
|
||||
["en"] = LocalizationFontProfile.English
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 生成启动器 UI 使用的 FontFamily。
|
||||
/// </summary>
|
||||
/// <param name="customFontName">用户自定义字体。为空时使用当前语言默认字体链。</param>
|
||||
/// <param name="language">目标语言。为空时使用当前 UI 语言。</param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成用于代表某种语言的 FontFamily。
|
||||
/// </summary>
|
||||
public static FontFamily BuildRepresentativeFontFamily(LocalizationLanguage language)
|
||||
{
|
||||
return BuildRepresentativeFontFamily(language.FontProfile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成用于代表某种字体策略的 FontFamily。
|
||||
/// </summary>
|
||||
public static FontFamily BuildRepresentativeFontFamily(LocalizationFontProfile profile)
|
||||
{
|
||||
return new FontFamily(_ApplicationPackUri, string.Join(", ", _GetDefaultFamilyNames(profile)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用启动器 UI 字体。
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据区域性名称解析字体策略。
|
||||
/// </summary>
|
||||
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<string> _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<string> _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(",", ",,");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user