Skip to content

feat(i18n): 国际化与本地化基础#2799

Open
Chiloven945 wants to merge 8 commits intodevfrom
feat/i18n
Open

feat(i18n): 国际化与本地化基础#2799
Chiloven945 wants to merge 8 commits intodevfrom
feat/i18n

Conversation

@Chiloven945
Copy link
Copy Markdown
Contributor

@Chiloven945 Chiloven945 commented May 4, 2026

实现 i18n 与 l10n 的基础能力。

待办:

  • 加载与调用语言文件
  • 配置记录语言与地区格式
  • 语言选项卡;UI 切换语言与日期格式
  • 初步接入本地化系统
  • 默认字体切换;文本显示本地化
  • 扩展 管理 -> 辅助功能 中的 游戏语言 以跟随启动器语言
image

Summary by Sourcery

为启动器引入一个全局本地化系统,用于 UI 语言和格式化区域设置,将其集成到设置中,并与 Minecraft 启动行为和字体处理进行连接。

New Features:

  • 添加本地化服务、语言模型和辅助工具,用于在运行时管理 UI 语言、格式化区域设置以及资源字典。
  • 添加启动器语言设置页面和配置分组,用于控制 UI 语言、格式化区域设置以及在安装向导导航中的可见性。
  • 引入字体本地化服务,用于根据语言和用户字体偏好选择并应用合适的字体族,并将其接入全局启动器字体设置和字体选择控件。

Enhancements:

  • 更新 Minecraft 预运行逻辑,从启动器本地化偏好中推导游戏语言和 Unicode 字体设置,同时保留特定版本的语言代码规则。
  • 调整安装向导的导航、可见性和重置流程,以包含新的启动器语言设置页面。
  • 让字体选择器响应语言变化,并使用本地化的默认字体。

Tests:

  • 添加测试以验证受支持语言的语言资源字典,并确保键名一致、不重复且具有有效的区域文化信息。
  • 添加测试以验证从区域文化名称解析字体配置文件,以及正确处理不受支持或别名语言代码的情况。
Original summary in English

Summary by Sourcery

Introduce a launcher-wide localization system for UI language and formatting culture, integrate it into settings, and connect it with Minecraft launch behavior and font handling.

New Features:

  • Add a localization service, language model, and helpers to manage UI language, formatting culture, and resource dictionaries at runtime.
  • Add a launcher language settings page and config group to control UI language, formatting culture, and visibility in setup navigation.
  • Introduce a font localization service to select and apply appropriate font families per language and user font preferences, and wire it to the global launcher font setting and font selector control.

Enhancements:

  • Update Minecraft pre-run logic to derive game language and Unicode font settings from launcher localization preferences while preserving version-specific language code rules.
  • Adjust setup navigation, visibility, and reset flows to include the new launcher language settings page.
  • Make the font selector respond to language changes and use localized default fonts.

Tests:

  • Add tests to validate language resource dictionaries for supported languages and ensure consistent, non-duplicated keys with valid cultures.
  • Add tests to verify font profile resolution from culture names and correct handling of unsupported or aliased language codes.

@Chiloven945 Chiloven945 added this to the I18n milestone May 4, 2026
@pcl-ce-automation pcl-ce-automation Bot added 🚧 正在处理 开发人员正在对该内容进行开发、测试或修复,进展中 size: XL PR 大小评估:超大型 labels May 4, 2026
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 4, 2026

审阅者指南

引入一个启动器范围的本地化系统,使 UI 语言、格式化区域文化以及特定语言的字体配置文件可以在运行时进行配置;将其接入到设置导航、字体选择以及 Minecraft 预运行阶段的语言/字体处理中,并添加测试来验证语言资源和字体配置文件解析的正确性。

从配置应用本地化并更新字体的时序图

sequenceDiagram
    actor User
    participant SettingsUI
    participant Config
    participant LocalizationService
    participant ApplicationResources
    participant LocalizationFontService
    participant FontSelector

    User->>SettingsUI: change UiLanguage or UiFormatCulture
    SettingsUI->>Config: update Preference.Localization values
    Config-->>LocalizationService: trigger OnLanguageConfigChanged
    LocalizationService->>LocalizationService: ApplyFromConfig(save=true)
    LocalizationService->>Config: read Localization.Language and FormatCulture
    LocalizationService->>LocalizationService: ResolveLanguage(languageCode)
    LocalizationService->>LocalizationService: _ResolveFormatCulture(formatCultureCode, uiCulture)
    LocalizationService->>LocalizationService: _ApplyCultures(uiCulture, formatCulture)
    LocalizationService->>ApplicationResources: _ApplyLanguageResources(languageCode)
    LocalizationService->>LocalizationFontService: ApplyLaunchFont(Config.Preference.Font, language)
    LocalizationFontService->>ApplicationResources: set LaunchFontFamily
    LocalizationService-->>Config: persist normalized Language and FormatCulture
    LocalizationService-->>LocalizationService: update CurrentLanguage and CurrentFormatCulture
    LocalizationService-->>FontSelector: LanguageChanged event
    FontSelector->>FontSelector: RefreshDefaultFont()
    FontSelector->>LocalizationFontService: BuildLaunchFontFamily()
    FontSelector->>FontSelector: update default CustomFontProperties.Font
Loading

Minecraft 预运行语言与字体处理的时序图

sequenceDiagram
    participant ModLaunch
    participant ModMinecraft
    participant LocalizationService
    participant ModBase
    participant McConfigIni as McConfigIni

    ModLaunch->>McConfigIni: ReadIni(lang)
    McConfigIni-->>ModLaunch: currentLang
    ModLaunch->>ModMinecraft: check saves directory
    ModMinecraft-->>ModLaunch: hasExistingSaves
    ModLaunch->>ModLaunch: isLanguageUnconfigured = (currentLang == none)
    ModLaunch->>ModLaunch: shouldUseDefault = isLanguageUnconfigured or !hasExistingSaves
    ModLaunch->>ModMinecraft: get ReleaseTime
    ModMinecraft-->>ModLaunch: mcReleaseTime
    ModLaunch->>ModLaunch: requiredLang = _ResolveMinecraftLanguage(currentLang, shouldUseDefault, mcReleaseTime)
    ModLaunch->>ModLaunch: compare currentLang and requiredLang
    alt language changed
        ModLaunch->>McConfigIni: WriteIni(lang, "-")
        ModLaunch->>McConfigIni: WriteIni(lang, requiredLang)
    end
    ModLaunch->>ModLaunch: if (isLanguageUnconfigured or !hasExistingSaves) and _ShouldEnableForceUnicodeFont()
    ModLaunch->>LocalizationService: CurrentLanguage
    LocalizationService-->>ModLaunch: LocalizationLanguage with FontProfile
    ModLaunch->>ModLaunch: _ShouldEnableForceUnicodeFont() based on FontProfile
    alt forceUnicodeFont enabled
        ModLaunch->>McConfigIni: WriteIni(forceUnicodeFont, true)
    end
Loading

新本地化系统(LocalizationService 及相关类型)的类图

classDiagram
    class LocalizationService {
        <<service>>
        +const string Auto
        +const string FormatCultureFollowLanguage
        +const string DefaultLanguageCode
        +static LocalizationLanguage CurrentLanguage
        +static CultureInfo CurrentFormatCulture
        +static IReadOnlyList~LocalizationLanguage~ SupportedLanguages
        +static event Action LanguageChanged
        +static void ApplyFromConfig(bool save)
        +static void Apply(string languageCode, string formatCultureCode, bool save)
        +static bool IsLanguageSupported(string languageCode)
        +static LocalizationLanguage ResolveLanguage(string languageCode)
        -static void _Start()
        -static void _ApplyCultures(CultureInfo uiCulture, CultureInfo formatCulture)
        -static void _ApplyLanguageResources(string languageCode, CultureInfo uiCulture, CultureInfo formatCulture)
        -static void _ApplyLanguageResourcesCore(Application app, string languageCode)
        -static CultureInfo _ResolveFormatCulture(string formatCultureCode, CultureInfo uiCulture, out string normalizedCode)
        -static LocalizationLanguage _ResolveSystemLanguage()
        -static void _SaveConfigIfNeeded(bool save, string normalizedLanguageCode, LocalizationLanguage language, string normalizedFormatCultureCode)
    }

    class LocalizationLanguage {
        +string Code
        +string NativeName
        +string CultureName
        +LocalizationFontProfile FontProfile
    }

    class LocalizationFontProfile {
        <<enum>>
        English
        SimplifiedChinese
        TraditionalChinese
        Japanese
        Korean
        Other
    }

    class LocalizationFontService {
        <<static>>
        -const string PclEnglishFont
        -Uri _ApplicationPackUri
        +FontFamily BuildLaunchFontFamily(string customFontName, LocalizationLanguage language)
        +FontFamily BuildRepresentativeFontFamily(LocalizationLanguage language)
        +FontFamily BuildRepresentativeFontFamily(LocalizationFontProfile profile)
        +void ApplyLaunchFont(string customFontName, LocalizationLanguage language)
        +LocalizationFontProfile ResolveProfileFromCultureName(string cultureName)
        -IReadOnlyList~string~ _GetDefaultFamilyNames(LocalizationFontProfile profile)
        -IReadOnlyList~string~ _GetCustomFamilyNames(string customFontName, LocalizationFontProfile profile)
    }

    class Lang {
        <<static>>
        +string Text(string key)
        +string Text(string key, object[] args)
        +string Date(DateTime value, string format)
        +string Number~T~(T value, string format)
        -object _LifecycleSafeFindResource(string key)
    }

    class LocalizationFormatConverter {
        +object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        +object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    }

    class LocalizationConfigGroup {
        +string Language
        +string FormatCulture
        +string Region
    }

    class ConfigPreferenceLocalization {
        +LocalizationConfigGroup Localization
    }

    class FontSelector {
        +ObservableCollection~CustomFontProperties~ CustomFontCollection
        +string Tooltip
        +string SelectedFontTag
        +int SelectedIndex
        +event SelectionChangedEventHandler SelectionChanged
        +void LoadFonts()
        +void RefreshDefaultFont()
        +void StartListeningLanguageChanged()
        +void StopListeningLanguageChanged()
        +void LocalizationService_LanguageChanged()
    }

    class CustomFontProperties {
        +string Name
        +FontFamily Font
        +string Tag
        +event PropertyChangedEventHandler PropertyChanged
        -void SetField~T~(T field, T value, string propertyName)
    }

    class ModBase {
        +static void SetLaunchFont(string FontName)
    }

    LocalizationService --> LocalizationLanguage : uses
    LocalizationService --> LocalizationFontService : ApplyLaunchFont
    LocalizationService --> LocalizationFontProfile : CurrentLanguage.FontProfile
    LocalizationService --> LocalizationConfigGroup : reads
    LocalizationFontService --> LocalizationFontProfile : ResolveProfileFromCultureName
    LocalizationFontService --> LocalizationLanguage : BuildLaunchFontFamily
    Lang --> LocalizationService : uses cultures
    LocalizationFormatConverter --> LocalizationService : uses CultureInfo
    ConfigPreferenceLocalization o-- LocalizationConfigGroup
    FontSelector --> LocalizationFontService : BuildLaunchFontFamily
    FontSelector ..> LocalizationService : subscribes LanguageChanged
    FontSelector o-- CustomFontProperties
    ModBase --> LocalizationFontService : ApplyLaunchFont
    ModBase --> LocalizationService : CurrentLanguage
Loading

文件级改动

变更 详情 文件
添加本地化服务、语言模型和资源访问辅助工具,用于在运行时管理 UI 语言和格式化区域文化。
  • 引入 LocalizationService,用于解析/应用 UI 语言和格式化区域文化,管理资源字典,并触发 LanguageChanged 事件。
  • 添加 LocalizationLanguage 和 LocalizationFontProfile 模型,用于表示受支持的语言及其字体配置文件。
  • 添加 Lang 辅助类和 LocalizationFormatConverter,用于在代码和 XAML 中进行本地化文本查找以及日期/数字的区域文化感知格式化。
PCL.Core/App/Localization/LocalizationService.cs
PCL.Core/App/Localization/LocalizationLanguage.cs
PCL.Core/App/Localization/LocalizationFontProfile.cs
PCL.Core/App/Localization/Lang.cs
PCL.Core/App/Localization/LocalizationFormatConverter.cs
将本地化配置以及新的启动器语言设置页面集成到现有的设置系统和导航中。
  • 添加 LocalizationConfigGroup(Language、FormatCulture、Region)以及用于控制启动器语言设置页面的新隐藏标志。
  • 创建 PageSetupLauncherLanguage(XAML + 代码后置),用于编辑 UI 语言/格式化区域文化,绑定到 Config.Preference.Localization,并调用 LocalizationService.ApplyFromConfig。
  • 将新页面接入 PageSetupLeft 导航、重置流程、PageSetupUI 中的隐藏/可见逻辑,以及 FormMain.PageSubType 和 ModMain 页面引用。
PCL.Core/App/Config.cs
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLauncherLanguage.xaml
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLauncherLanguage.xaml.cs
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLeft.xaml
Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.cs
Plain Craft Launcher 2/FormMain.xaml.cs
Plain Craft Launcher 2/Modules/ModMain.cs
Plain Craft Launcher 2/Modules/ModSetup.cs
本地化启动器字体处理,使 FontSelector 能对语言变化和本地化默认字体做出响应。
  • 引入 LocalizationFontService,用于从区域文化解析字体配置文件,并构建/应用适用于当前语言的 FontFamily 回退集合。
  • 更新 ModBase.SetLaunchFont,使其通过当前语言配置文件将字体应用委托给 LocalizationFontService。
  • 重构 FontSelector,使其对默认项使用 LocalizationFontService,监听 LocalizationService.LanguageChanged,并更新 CustomFontProperties 以支持属性变更通知和动态默认字体更新。
PCL.Core/App/Localization/LocalizationFontService.cs
Plain Craft Launcher 2/Modules/Base/ModBase.cs
Plain Craft Launcher 2/Controls/FontSelector.xaml.cs
让 Minecraft 预运行阶段的语言和 Unicode 字体设置与启动器本地化偏好保持一致,并扩展游戏管理辅助选项。
  • 重构 McLaunchPrerun,通过辅助方法计算所需的 Minecraft 语言,这些方法会考虑启动器语言(LocalizationService.CurrentLanguage)以及特定版本的语言代码大小写。
  • 添加 _ShouldEnableForceUnicodeFont,使其基于当前语言的字体配置文件(CJK 语言)启用 forceUnicodeFont,而不是硬编码仅针对中文的逻辑。
  • 重命名并重新绑定游戏管理复选框,使其跟随启动器语言(AutoChangeLanguage),而不是中国地区专用的辅助标志。
Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.cs
Plain Craft Launcher 2/Pages/PageSetup/PageSetupGameManage.xaml
Plain Craft Launcher 2/Pages/PageSetup/PageSetupGameManage.xaml.cs
添加语言资源字典以及测试,以确保语言支持和字体配置文件解析的正确性。
  • 为每种受支持语言添加 XAML 资源字典(zh-CN、zh-TW、en-US、en-GB、ja-JP、fr-FR、es-ES)。
  • 添加 LocalizationTest,用于验证所有受支持语言是否拥有资源文件、键是否一致且无重复,以及区域文化是否有效。
  • 添加测试,验证 LocalizationFontService.ResolveProfileFromCultureName 的行为,并确保字体配置文件别名不会隐式地在 LocalizationService 中将语言标记为受支持。
PCL.Core/App/Localization/Languages/zh-CN.xaml
PCL.Core/App/Localization/Languages/zh-TW.xaml
PCL.Core/App/Localization/Languages/en-US.xaml
PCL.Core/App/Localization/Languages/en-GB.xaml
PCL.Core/App/Localization/Languages/ja-JP.xaml
PCL.Core/App/Localization/Languages/fr-FR.xaml
PCL.Core/App/Localization/Languages/es-ES.xaml
PCL.Core.Test/LocalizationTest.cs

技巧与命令

与 Sourcery 交互

  • 触发新的审查: 在拉取请求中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 从审查评论生成 GitHub issue: 在某条审查评论下回复,要求 Sourcery 从该评论创建一个 issue。你也可以在审查评论下回复 @sourcery-ai issue,以此从该评论创建 issue。
  • 生成拉取请求标题: 在拉取请求标题的任意位置写入 @sourcery-ai,即可随时生成标题。你也可以在拉取请求中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成拉取请求摘要: 在拉取请求正文任意位置写入 @sourcery-ai summary,即可在该位置生成 PR 摘要。你也可以在拉取请求中评论 @sourcery-ai summary 来随时(重新)生成摘要。
  • 生成审阅者指南: 在拉取请求中评论 @sourcery-ai guide,即可随时(重新)生成审阅者指南。
  • 解决所有 Sourcery 评论: 在拉取请求中评论 @sourcery-ai resolve,即可标记所有 Sourcery 评论为已解决。如果你已经处理完所有评论且不想再看到它们,这会很有用。
  • 取消所有 Sourcery 审查: 在拉取请求中评论 @sourcery-ai dismiss,即可取消所有现有的 Sourcery 审查。尤其适用于你想在一次全新的审查中重新开始的情况——别忘了再评论 @sourcery-ai review 以触发新的审查!

自定义你的体验

访问你的 控制面板,以便:

  • 启用或禁用审查功能,例如 Sourcery 生成的拉取请求摘要、审阅者指南等。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查指令。
  • 调整其他审查设置。

获取帮助

Original review guide in English

Reviewer's Guide

Introduce a launcher-wide localization system with runtime-configurable UI language, formatting culture, and language-specific font profiles, wire it into setup navigation, font selection, and Minecraft pre-run language/font handling, and add tests to validate language resources and font profile resolution.

Sequence diagram for applying localization from config and updating fonts

sequenceDiagram
    actor User
    participant SettingsUI
    participant Config
    participant LocalizationService
    participant ApplicationResources
    participant LocalizationFontService
    participant FontSelector

    User->>SettingsUI: change UiLanguage or UiFormatCulture
    SettingsUI->>Config: update Preference.Localization values
    Config-->>LocalizationService: trigger OnLanguageConfigChanged
    LocalizationService->>LocalizationService: ApplyFromConfig(save=true)
    LocalizationService->>Config: read Localization.Language and FormatCulture
    LocalizationService->>LocalizationService: ResolveLanguage(languageCode)
    LocalizationService->>LocalizationService: _ResolveFormatCulture(formatCultureCode, uiCulture)
    LocalizationService->>LocalizationService: _ApplyCultures(uiCulture, formatCulture)
    LocalizationService->>ApplicationResources: _ApplyLanguageResources(languageCode)
    LocalizationService->>LocalizationFontService: ApplyLaunchFont(Config.Preference.Font, language)
    LocalizationFontService->>ApplicationResources: set LaunchFontFamily
    LocalizationService-->>Config: persist normalized Language and FormatCulture
    LocalizationService-->>LocalizationService: update CurrentLanguage and CurrentFormatCulture
    LocalizationService-->>FontSelector: LanguageChanged event
    FontSelector->>FontSelector: RefreshDefaultFont()
    FontSelector->>LocalizationFontService: BuildLaunchFontFamily()
    FontSelector->>FontSelector: update default CustomFontProperties.Font
Loading

Sequence diagram for Minecraft pre-run language and font handling

sequenceDiagram
    participant ModLaunch
    participant ModMinecraft
    participant LocalizationService
    participant ModBase
    participant McConfigIni as McConfigIni

    ModLaunch->>McConfigIni: ReadIni(lang)
    McConfigIni-->>ModLaunch: currentLang
    ModLaunch->>ModMinecraft: check saves directory
    ModMinecraft-->>ModLaunch: hasExistingSaves
    ModLaunch->>ModLaunch: isLanguageUnconfigured = (currentLang == none)
    ModLaunch->>ModLaunch: shouldUseDefault = isLanguageUnconfigured or !hasExistingSaves
    ModLaunch->>ModMinecraft: get ReleaseTime
    ModMinecraft-->>ModLaunch: mcReleaseTime
    ModLaunch->>ModLaunch: requiredLang = _ResolveMinecraftLanguage(currentLang, shouldUseDefault, mcReleaseTime)
    ModLaunch->>ModLaunch: compare currentLang and requiredLang
    alt language changed
        ModLaunch->>McConfigIni: WriteIni(lang, "-")
        ModLaunch->>McConfigIni: WriteIni(lang, requiredLang)
    end
    ModLaunch->>ModLaunch: if (isLanguageUnconfigured or !hasExistingSaves) and _ShouldEnableForceUnicodeFont()
    ModLaunch->>LocalizationService: CurrentLanguage
    LocalizationService-->>ModLaunch: LocalizationLanguage with FontProfile
    ModLaunch->>ModLaunch: _ShouldEnableForceUnicodeFont() based on FontProfile
    alt forceUnicodeFont enabled
        ModLaunch->>McConfigIni: WriteIni(forceUnicodeFont, true)
    end
Loading

Class diagram for new localization system (LocalizationService and related types)

classDiagram
    class LocalizationService {
        <<service>>
        +const string Auto
        +const string FormatCultureFollowLanguage
        +const string DefaultLanguageCode
        +static LocalizationLanguage CurrentLanguage
        +static CultureInfo CurrentFormatCulture
        +static IReadOnlyList~LocalizationLanguage~ SupportedLanguages
        +static event Action LanguageChanged
        +static void ApplyFromConfig(bool save)
        +static void Apply(string languageCode, string formatCultureCode, bool save)
        +static bool IsLanguageSupported(string languageCode)
        +static LocalizationLanguage ResolveLanguage(string languageCode)
        -static void _Start()
        -static void _ApplyCultures(CultureInfo uiCulture, CultureInfo formatCulture)
        -static void _ApplyLanguageResources(string languageCode, CultureInfo uiCulture, CultureInfo formatCulture)
        -static void _ApplyLanguageResourcesCore(Application app, string languageCode)
        -static CultureInfo _ResolveFormatCulture(string formatCultureCode, CultureInfo uiCulture, out string normalizedCode)
        -static LocalizationLanguage _ResolveSystemLanguage()
        -static void _SaveConfigIfNeeded(bool save, string normalizedLanguageCode, LocalizationLanguage language, string normalizedFormatCultureCode)
    }

    class LocalizationLanguage {
        +string Code
        +string NativeName
        +string CultureName
        +LocalizationFontProfile FontProfile
    }

    class LocalizationFontProfile {
        <<enum>>
        English
        SimplifiedChinese
        TraditionalChinese
        Japanese
        Korean
        Other
    }

    class LocalizationFontService {
        <<static>>
        -const string PclEnglishFont
        -Uri _ApplicationPackUri
        +FontFamily BuildLaunchFontFamily(string customFontName, LocalizationLanguage language)
        +FontFamily BuildRepresentativeFontFamily(LocalizationLanguage language)
        +FontFamily BuildRepresentativeFontFamily(LocalizationFontProfile profile)
        +void ApplyLaunchFont(string customFontName, LocalizationLanguage language)
        +LocalizationFontProfile ResolveProfileFromCultureName(string cultureName)
        -IReadOnlyList~string~ _GetDefaultFamilyNames(LocalizationFontProfile profile)
        -IReadOnlyList~string~ _GetCustomFamilyNames(string customFontName, LocalizationFontProfile profile)
    }

    class Lang {
        <<static>>
        +string Text(string key)
        +string Text(string key, object[] args)
        +string Date(DateTime value, string format)
        +string Number~T~(T value, string format)
        -object _LifecycleSafeFindResource(string key)
    }

    class LocalizationFormatConverter {
        +object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        +object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    }

    class LocalizationConfigGroup {
        +string Language
        +string FormatCulture
        +string Region
    }

    class ConfigPreferenceLocalization {
        +LocalizationConfigGroup Localization
    }

    class FontSelector {
        +ObservableCollection~CustomFontProperties~ CustomFontCollection
        +string Tooltip
        +string SelectedFontTag
        +int SelectedIndex
        +event SelectionChangedEventHandler SelectionChanged
        +void LoadFonts()
        +void RefreshDefaultFont()
        +void StartListeningLanguageChanged()
        +void StopListeningLanguageChanged()
        +void LocalizationService_LanguageChanged()
    }

    class CustomFontProperties {
        +string Name
        +FontFamily Font
        +string Tag
        +event PropertyChangedEventHandler PropertyChanged
        -void SetField~T~(T field, T value, string propertyName)
    }

    class ModBase {
        +static void SetLaunchFont(string FontName)
    }

    LocalizationService --> LocalizationLanguage : uses
    LocalizationService --> LocalizationFontService : ApplyLaunchFont
    LocalizationService --> LocalizationFontProfile : CurrentLanguage.FontProfile
    LocalizationService --> LocalizationConfigGroup : reads
    LocalizationFontService --> LocalizationFontProfile : ResolveProfileFromCultureName
    LocalizationFontService --> LocalizationLanguage : BuildLaunchFontFamily
    Lang --> LocalizationService : uses cultures
    LocalizationFormatConverter --> LocalizationService : uses CultureInfo
    ConfigPreferenceLocalization o-- LocalizationConfigGroup
    FontSelector --> LocalizationFontService : BuildLaunchFontFamily
    FontSelector ..> LocalizationService : subscribes LanguageChanged
    FontSelector o-- CustomFontProperties
    ModBase --> LocalizationFontService : ApplyLaunchFont
    ModBase --> LocalizationService : CurrentLanguage
Loading

File-Level Changes

Change Details Files
Add localization service, language model, and resource access helpers to manage UI language and formatting culture at runtime.
  • Introduce LocalizationService to resolve/apply UI languages and format cultures, manage resource dictionaries, and raise LanguageChanged events.
  • Add LocalizationLanguage and LocalizationFontProfile models to represent supported languages and their font profiles.
  • Add Lang helper and LocalizationFormatConverter for localized text lookup and culture-aware formatting of dates/numbers in code and XAML.
PCL.Core/App/Localization/LocalizationService.cs
PCL.Core/App/Localization/LocalizationLanguage.cs
PCL.Core/App/Localization/LocalizationFontProfile.cs
PCL.Core/App/Localization/Lang.cs
PCL.Core/App/Localization/LocalizationFormatConverter.cs
Integrate localization configuration and a new launcher language setup page into the existing settings system and navigation.
  • Add LocalizationConfigGroup (Language, FormatCulture, Region) and new hide flag for the launcher language setup page.
  • Create PageSetupLauncherLanguage (XAML + code-behind) to edit UI language/format culture, bind to Config.Preference.Localization, and call LocalizationService.ApplyFromConfig.
  • Wire the new page into PageSetupLeft navigation, reset flow, hide/visibility logic in PageSetupUI, FormMain.PageSubType, and ModMain page references.
PCL.Core/App/Config.cs
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLauncherLanguage.xaml
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLauncherLanguage.xaml.cs
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLeft.xaml
Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.cs
Plain Craft Launcher 2/FormMain.xaml.cs
Plain Craft Launcher 2/Modules/ModMain.cs
Plain Craft Launcher 2/Modules/ModSetup.cs
Localize launcher font handling and make FontSelector respond to language changes and localized default fonts.
  • Introduce LocalizationFontService to resolve font profiles from cultures and build/apply language-appropriate FontFamily fallbacks.
  • Update ModBase.SetLaunchFont to delegate font application to LocalizationFontService using the current language profile.
  • Refactor FontSelector to use LocalizationFontService for the default item, listen to LocalizationService.LanguageChanged, and update CustomFontProperties to support property change notifications and dynamic default font updates.
PCL.Core/App/Localization/LocalizationFontService.cs
Plain Craft Launcher 2/Modules/Base/ModBase.cs
Plain Craft Launcher 2/Controls/FontSelector.xaml.cs
Align Minecraft pre-run language and Unicode font settings with launcher localization preferences and extend game-manage helper option.
  • Refactor McLaunchPrerun to compute the required Minecraft language via helper methods that consider launcher language (LocalizationService.CurrentLanguage) and version-specific language code casing.
  • Add _ShouldEnableForceUnicodeFont that enables forceUnicodeFont based on the current language’s font profile (CJK languages) instead of hard-coded Chinese-only logic.
  • Rename and rebind the game manage checkbox to follow launcher language (AutoChangeLanguage) rather than a China-specific helper flag.
Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.cs
Plain Craft Launcher 2/Pages/PageSetup/PageSetupGameManage.xaml
Plain Craft Launcher 2/Pages/PageSetup/PageSetupGameManage.xaml.cs
Add language resource dictionaries and tests to ensure language support and font profile resolution correctness.
  • Add XAML resource dictionaries for each supported language (zh-CN, zh-TW, en-US, en-GB, ja-JP, fr-FR, es-ES).
  • Add LocalizationTest to validate that all supported languages have resource files, keys are consistent and non-duplicated, and cultures are valid.
  • Add tests to verify LocalizationFontService.ResolveProfileFromCultureName behavior and ensure font profile aliases do not implicitly mark languages as supported in LocalizationService.
PCL.Core/App/Localization/Languages/zh-CN.xaml
PCL.Core/App/Localization/Languages/zh-TW.xaml
PCL.Core/App/Localization/Languages/en-US.xaml
PCL.Core/App/Localization/Languages/en-GB.xaml
PCL.Core/App/Localization/Languages/ja-JP.xaml
PCL.Core/App/Localization/Languages/fr-FR.xaml
PCL.Core/App/Localization/Languages/es-ES.xaml
PCL.Core.Test/LocalizationTest.cs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@Chiloven945
Copy link
Copy Markdown
Contributor Author

Chiloven945 commented May 6, 2026

还是那个老问题,内置的 Font.ttf aka. PCL English 只支持了一些基础的 ASCII 字符。这意味着任何拥有附加符号(变音符号)的语言,如西班牙语、葡萄牙语等,将出现很多一些以 PCL English 显示而一些由系统默认字体(Segoe UI)显示的情况。除此之外,在和一些非拉丁字母(希腊字母、西里尔字母)一起显示时也会略显怪异。

image image

本人能想到的有两种解决办法:

  1. 在出现问题的字体直接使用 Segoe UI 字体。仅 CJK 和英语使用 PCL English。
  2. 找一款相似的字体代替。其中可以考虑 Bahnschrift 字体,因其内置于 Windows 10 与 Windows 11,且无需担心因打包分发的版权问题。

下图展示了 PCL English(下)和 Bahnschrift Light(上)的区别。两者极为相似,只有仔细对比观察才能发现区别。因此可以考虑作为替代字体。

image

Edited: 暂时选择方案一为解决办法,待讨论。

附上效果图
字体 图片
PCL English Screenshot 2026-05-06 173255
Bahnschrift Light Screenshot 2026-05-06 173130
Bahnschrift SemiLight Screenshot 2026-05-06 173211
Segoe UI Screenshot 2026-05-06 172727

@pcl-ce-automation pcl-ce-automation Bot added size: XXL PR 大小评估:巨型 and removed size: XL PR 大小评估:超大型 labels May 6, 2026
@Chiloven945

This comment was marked as resolved.

sourcery-ai[bot]

This comment was marked as resolved.

@Chiloven945

This comment was marked as resolved.

sourcery-ai[bot]

This comment was marked as resolved.

oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
@Chiloven945 Chiloven945 marked this pull request as ready for review May 7, 2026 01:17
@pcl-ce-automation pcl-ce-automation Bot added 🛠️ 等待审查 Pull Request 已完善,等待维护者或负责人进行代码审查 and removed 🚧 正在处理 开发人员正在对该内容进行开发、测试或修复,进展中 labels May 7, 2026
@Chiloven945 Chiloven945 requested a review from a team May 7, 2026 01:18
sourcery-ai[bot]

This comment was marked as spam.

Copy link
Copy Markdown
Member

@SALTWOOD SALTWOOD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

多个原本为 UTF-8 的文件在此 PR 被修改为了 UTF-8 with BOM

  • Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.cs:1
  • Plain Craft Launcher 2/Pages/PageSetup/PageSetupGameManage.xaml.cs:1
  • Plain Craft Launcher 2/Pages/PageSetup/PageSetupLeft.xaml:1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: XXL PR 大小评估:巨型 🛠️ 等待审查 Pull Request 已完善,等待维护者或负责人进行代码审查

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants