Merge #1973: Fix incomplete system font coverage in the Chinese interface (@yuraizmailov)

This commit is contained in:
aiongg
2026-10-23 21:19:31 +00:00
3 changed files with 19 additions and 2 deletions
+2
View File
@@ -10,6 +10,8 @@ pub(crate) mod effects;
/// Translations for the panels, tooltips and dialogs below the menu bar (see the module docs).
mod ui;
use effectcraft_engine::menus::{MenuEntry, MenuNode};
#[cfg(not(target_arch = "wasm32"))]
pub(crate) use ui::catalog_characters;
pub(crate) use ui::{set_current, tr, tr_args};
/// Every language with a catalog, in the order Settings ▸ General ▸ Language lists them.
+7
View File
@@ -84,6 +84,13 @@ pub(super) fn missing(language: &str) -> Vec<&'static str> {
ROWS.iter().flat_map(|(_, rows)| rows.iter().map(|(en, _)| *en)).filter(|en| seen.insert(*en) && !table.is_some_and(|c| c.contains_key(en))).collect()
}
/// Characters required by the fixed panel catalog, for system-font coverage selection.
/// Sorted and deduplicated so fallback registration is deterministic.
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn catalog_characters(language: &str) -> Vec<char> {
catalog(language).into_iter().flat_map(|c| c.values()).flat_map(|s| s.chars()).collect::<std::collections::BTreeSet<_>>().into_iter().collect()
}
/// Translate one interface string: the current language's row for `text`, or `text` itself.
pub(crate) fn tr(text: &str) -> &str {
catalog(current()).and_then(|c| c.get(text)).copied().unwrap_or(text)
+10 -2
View File
@@ -408,7 +408,14 @@ fn install_script_fallbacks(family_fonts: &mut FontDefinitions, language: &str)
let cjk = if is_chinese(language) { [han, KANA] } else { [KANA, han] };
let mut names = Vec::new();
let mut seen = Vec::new();
for &(probe, name) in cjk.iter().chain(SCRIPT_PROBES).chain(std::iter::once(&HANGUL)) {
// A font covering one Han probe may be a sparse subset. Register additional faces
// needed by the actual interface catalog instead of assuming whole-script coverage.
let extra = if is_chinese(language) { crate::i18n::catalog_characters(language) } else { Vec::new() };
let extra: Vec<_> = extra.into_iter().filter(|ch| *ch >= '\u{2e80}').map(|ch| (ch, "catalog-system")).collect();
for &(probe, name) in cjk.iter().chain(SCRIPT_PROBES).chain(std::iter::once(&HANGUL)).chain(&extra) {
if name == "catalog-system" && seen.iter().any(|&id| fonts::face(id).has_char(probe)) {
continue;
}
// The interface asks for the platform's UI face first; the order a composed frame
// renders with is `fonts::fallback_for`'s and is not touched here. Another context may
// install a different language concurrently, so the shared fallback is asked with this
@@ -432,7 +439,8 @@ fn install_script_fallbacks(family_fonts: &mut FontDefinitions, language: &str)
// Use the already-read, parsed bytes rather than reading a font file twice.
let mut data = FontData::from_owned(font.data().as_bytes().to_vec());
data.index = face.info.index;
family_fonts.font_data.insert(name.to_string(), Arc::new(data));
let name = if name == "catalog-system" { format!("{name}-{:x}", probe as u32) } else { name.to_string() };
family_fonts.font_data.insert(name.clone(), Arc::new(data));
for family in family_fonts.families.values_mut() {
family.push(name.to_string());
}