{"id":38548827,"url":"https://github.com/krystic/flutter-arm-cjk-fix","last_synced_at":"2026-06-12T04:01:26.398Z","repository":{"id":329373663,"uuid":"1119310098","full_name":"krystic/flutter-arm-cjk-fix","owner":"krystic","description":"🚀 Fix Chinese/Japanese/Korean font display issues (squares/tofu) for Flutter apps on ARM64 Linux (Ubuntu/Snap). One-click restoration of CJK characters for App Center, Security Center, and more.","archived":false,"fork":false,"pushed_at":"2026-06-01T21:34:46.000Z","size":114639,"stargazers_count":12,"open_issues_count":0,"forks_count":4,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-01T23:21:11.898Z","etag":null,"topics":["aarch64","arm64","cjk-font","flutter","font-fix","linux","ubuntu"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/krystic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-19T04:37:46.000Z","updated_at":"2026-06-01T21:34:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/krystic/flutter-arm-cjk-fix","commit_stats":null,"previous_names":["krystic/flutter-arm-cjk-fix"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/krystic/flutter-arm-cjk-fix","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krystic%2Fflutter-arm-cjk-fix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krystic%2Fflutter-arm-cjk-fix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krystic%2Fflutter-arm-cjk-fix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krystic%2Fflutter-arm-cjk-fix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krystic","download_url":"https://codeload.github.com/krystic/flutter-arm-cjk-fix/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krystic%2Fflutter-arm-cjk-fix/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34228097,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aarch64","arm64","cjk-font","flutter","font-fix","linux","ubuntu"],"created_at":"2026-01-17T07:29:25.706Z","updated_at":"2026-06-12T04:01:26.362Z","avatar_url":"https://github.com/krystic.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flutter ARM CJK Font Fix\n\n[![缩略图](images/snap-store-screenshot-thumb.png)](images/snap-store-screenshot.png)\n\n**Ubuntu ARM 平台下 Flutter 应用 CJK 字体显示修复工具**\n\n针对在 Ubuntu ARM 架构上运行的 Flutter 应用（Snap 和非 Snap）出现 CJK（中日韩）字符显示为方框（豆腐块）的问题，提供系统级自动修复方案。\n\n\u003e **适用范围**：支持 Snap 应用（如 snap-store）和非 Snap 应用（如 rustdesk、AppImage、deb 包等）。通过 Engine Hash 自动检测 Flutter 版本，智能匹配和替换 SO 文件。\n\u003e\n\u003e **Scope**: Supports both Snap apps (snap-store) and non-Snap apps (rustdesk, AppImage, deb packages, etc.). Auto-detects Flutter version via Engine Hash for intelligent SO file matching.\n\n---\n\n## 📝 背景与原理\n\n### 问题现象\n在 ARM 架构（树莓派、飞腾、RK3588、Parallels 虚拟机等）运行 Ubuntu 时，许多由 Flutter 引擎构建的应用会出现 CJK 字符显示为方框。\n\n### 根本原因（已验证）\n\n**问题已彻底定位**：通过自编译 Flutter Engine 并对比官方版本，确认核心原因是官方 ARM64 版本 `libflutter_linux_gtk.so` **未链接 Fontconfig 库**。\n\n#### 技术层面\nFlutter 文本渲染链：`Flutter App → libflutter_linux_gtk.so → Skia → FontConfig`\n\n**验证方法**：\n```bash\n# 官方 ARM64 版本（缺陷）\nreadelf -d libflutter_linux_gtk.so | grep fontconfig\n# (无输出)\n\n# 自编译修复版本\nreadelf -d libflutter_linux_gtk.so | grep fontconfig\n# 0x0000000000000001 (NEEDED)  共享库：[libfontconfig.so.1]\n```\n\n#### 构建配置缺陷\n- **x64 平台**（正常）：使用 `linux_host_desktop_engine.json` 配置，包含 `--enable-fontconfig` 参数\n- **ARM64 平台**（缺陷）：使用 `linux_arm_host_engine.json` 配置，**缺少** `--enable-fontconfig` 参数\n- **架构失误**：官方将桌面目标和嵌入式目标混在同一个配置中，导致桌面版继承了嵌入式的\"精简\"配置\n\n#### 后果\n- Fontconfig 未启用 → Flutter Engine 无法发现系统字体\n- 字体回退机制失效 → CJK 字符找不到可用字体\n- 最终表现 → 显示为方框（□□□）\n\n**详细技术分析见**：[FONTCONFIG_BUG_INVESTIGATION.md](FONTCONFIG_BUG_INVESTIGATION.md)\n\n### 解决方案\n\n本项目由 **Krystic** 使用 **VS Code + GitHub Copilot + Claude Sonnet 4.5** 协同开发，最终根本原因的定位得益于自编译对比验证。\n\n#### 根治方案（推荐）\n通过自编译启用 Fontconfig 支持的 Flutter Engine SO 文件（`libflutter_linux_gtk.so`），使用 `mount --bind` 替换应用内的官方 SO，从根本上解决字体渲染问题。\n\n- ✅ 完全修复 Fontconfig 支持\n- ✅ 支持所有语言字符（不限于 CJK）\n- ✅ 自动版本检测和智能匹配\n- ✅ 版本缓存机制（提升启动速度）\n- ✅ Systemd 开机自启\n\n**编译说明**：[FONTCONFIG_BUG_INVESTIGATION.md](FONTCONFIG_BUG_INVESTIGATION.md)\n\n#### 兜底方案\n如果没有匹配的 SO 文件，自动回退到字体映射方案：通过 `mount --bind` 将 Noto Sans CJK 字体动态挂载到 Snap 应用内的 Ubuntu 字体路径。\n\n- ⚠️ 仅修复 CJK 字符显示\n- ⚠️ 其他语言符号可能仍显示为方框\n\n---\n\n## ✨ 特性\n\n### 核心功能\n* 🎯 **双应用类型支持**\n  - **Snap 应用**（`-a` 模式）：自动检测 Flutter 版本，使用精确匹配的 SO 文件，无匹配时回退到字体映射\n  - **非 Snap 应用**（`-e` 模式）：支持直接指定可执行文件路径，智能提取 SO 信息，支持相似版本选择\n* 🔍 **版本智能检测**\n  - **Hash 精确匹配**：通过 SO 文件中的 Engine Hash 精确识别 Flutter 版本\n  - **版本缓存机制**：缓存 Flutter 版本对照表（7天），避免重复网络请求\n  - **双源查找**：同时查找本地库和 GitHub 仓库，本地精确版本时自动跳过线上查询\n* 📦 **自动下载**：在线 SO 文件自动下载到本地（带进度条），支持 CDN 加速\n* 🔄 **开机自启**：自动创建 Systemd 服务，系统重启后静默恢复所有映射\n* 🛠️ **智能管理**\n  - 自动安装字体依赖（`fonts-noto-cjk`）\n  - 冲突检测（SO 替换与字体映射模式智能切换）\n  - 配置持久化（`/etc/flutter-cjk/`）\n  - Tab 自动补全（Snap 应用名称 + 文件路径）\n\n### 用户体验\n* 📋 **列表查看**：显示已映射应用的简要或详细信息\n* 🌐 **双语输出**：所有信息提供中英文对照\n* 🎨 **格式规范**：统一的 `[INFO]` / `[OK]` / `[ERROR]` / `[WARN]` 标签\n* ⚡ **即时生效**：无需重启应用，映射立即应用\n\n---\n\n## 🚀 快速开始\n\n### 安装\n\n#### 方式 1：一键安装（推荐）\n```bash\ncurl -fsSL https://raw.githubusercontent.com/krystic/flutter-arm-cjk-fix/main/install.sh | sudo bash\n```\n\n**功能**：\n- ✅ 自动检测 ARM64 Linux 架构（非 ARM64 会提示并退出）\n- ✅ 安装主脚本到 `/usr/local/bin/flutter-font-fix`\n- ✅ 安装必要依赖（`bash-completion`, `fonts-noto-cjk`）\n- ✅ 初始化配置目录（`/etc/flutter-cjk/`）\n- ✅ 注册并启用 systemd 服务\n- ✅ 安装 Bash 自动补全\n\n#### 方式 2：手动安装\n```bash\n# 下载脚本\nsudo wget https://github.com/krystic/flutter-arm-cjk-fix/raw/main/flutter-font-fix \\\n  -O /usr/local/bin/flutter-font-fix\n\n# 赋予执行权限\nsudo chmod +x /usr/local/bin/flutter-font-fix\n\n# 首次运行初始化（创建配置文件）\nsudo flutter-font-fix -l\n\n# 安装 Tab 补全（可选）\nsudo flutter-font-fix -i\n\n# 安装 systemd 服务（可选）\nsudo flutter-font-fix --install-service\n```\n\n### 基本用法\n\n#### 1. 修复 Snap 应用\n使用精确版本的 SO 文件替换，无匹配时回退到字体映射：\n```bash\nsudo flutter-font-fix -a snap-store\n\n# 输出示例：\n# [OK] [snap-store] Flutter Engine replaced with libflutter_linux_gtk.so.3.38.1\n#      Flutter 引擎已替换，字体问题已根治。\n```\n\n#### 2. 修复非 Snap 应用\n支持精确版本和相似版本选择（如 3.24.3 用于 3.24.5）：\n```bash\nsudo flutter-font-fix -e rustdesk\n# 或\nsudo flutter-font-fix -e /usr/bin/rustdesk\n\n# 相似版本选择示例：\n# [WARN] No exact version found for 3.24.5\n# [INFO] Found compatible versions:\n#   [1] 3.24.3 [本地/local]\n#   [2] 3.24.1 [线上/online]\n# 尝试这些版本之一吗？[1]: \n```\n\n**工作原理**：\n- 从 SO 文件提取 40 位 Engine Hash\n- 查询 Flutter GitHub 匹配版本（7 天缓存）\n- 本地精确版本时自动跳过线上查询\n- 支持 CDN 加速：`--cdn https://raw.staticdn.net/`\n\n#### 3. 自定义字体修复\n交互式选择应用内的字体文件并映射：\n```bash\nsudo flutter-font-fix -c snap-store\n\n# 脚本会：\n# 1. 搜索应用内所有字体文件\n# 2. 显示编号列表供选择（支持逗号分隔多选，'a' 全选）\n# 3. 为每个字体选择目标 Noto 字重（Regular/Bold/Light/Medium）\n# 4. 保存配置并立即应用\n```\n\n#### 4. 查看和管理\n```bash\n# 简要列表\nflutter-font-fix -l\n\n# 详细信息\nflutter-font-fix -d\n\n# 移除映射\nsudo flutter-font-fix -r \u003capp_name\u003e\n\n# 移除全部\nsudo flutter-font-fix --remove-all\n```\n\n---\n\n## 📖 命令参考\n\n### 主要命令\n\n| 命令 | 功能说明 |\n|------|---------|\n| `sudo flutter-font-fix -e \u003cexe\u003e` | 修复非 Snap 应用（支持精确+相似版本）\u003cbr\u003eRepair non-Snap apps (exact + similar versions) |\n| `sudo flutter-font-fix -a \u003capp\u003e` | 修复 Snap 应用（仅精确版本，回退字体映射）\u003cbr\u003eRepair Snap apps (exact version only, fallback to font mapping) |\n| `sudo flutter-font-fix -c \u003capp\u003e` | 自定义字体修复 Snap 应用\u003cbr\u003eRepair Snap apps with custom fonts |\n| `sudo flutter-font-fix -r \u003capp\u003e` | 移除/卸载映射（包括 SO 和字体）\u003cbr\u003eRemove/unmount mappings (SO and fonts) |\n| `flutter-font-fix -l \\| --list` | 列出已映射应用\u003cbr\u003eList mapped apps |\n| `flutter-font-fix -d \\| --detail` | 详细映射信息\u003cbr\u003eDetail mappings |\n| `sudo flutter-font-fix --remove-all` | 移除全部\u003cbr\u003eRemove all |\n| `sudo flutter-font-fix --uninstall-service` | 卸载系统服务\u003cbr\u003eUninstall systemd service |\n| `sudo flutter-font-fix --uninstall` | 完全卸载\u003cbr\u003eUninstall completely |\n| `sudo flutter-font-fix -i \\| --install-completion` | 安装补全\u003cbr\u003eInstall completion |\n\n### 全局参数\n\n| 参数 | 功能说明 |\n|------|---------|\n| `--cdn \u003cprefix\u003e` | 覆盖 GitHub Raw CDN 前缀（含末尾斜杠）\u003cbr\u003eOverride GitHub Raw CDN prefix (with trailing slash) |\n\n### 高级选项\n\n**CDN 加速**\n```bash\n# 使用 CDN 镜像\nsudo flutter-font-fix --cdn https://raw.staticdn.net/ -a snap-store\nsudo flutter-font-fix --cdn https://ghproxy.com/https://raw.githubusercontent.com/ -e rustdesk\n```\n\n**完全卸载**\n```bash\nsudo flutter-font-fix --uninstall\n```\n\n### 使用示例\n\n**修复 Snap Store**\n```bash\nsudo flutter-font-fix -a snap-store\n```\n\n**修复 rustdesk**\n```bash\nsudo flutter-font-fix -e rustdesk\n```\n\n**查看状态**\n```bash\nflutter-font-fix -d\n# 输出：\n# - snap-store [so/SO替换]\n#     • Flutter Engine: libflutter_linux_gtk.so.3.38.1\n# - rustdesk [so/SO替换]\n#     • Flutter Engine: libflutter_linux_gtk.so.3.24.3\n```\n\n---\n\n## 📂 文件结构\n\n```\n/etc/flutter-cjk/                      # 配置目录\n├── ubuntu.conf                        # 官方模式应用列表（格式：app|so 或 app|font）\n├── flutter.engine.hash.version        # Flutter Engine Hash→版本对照表缓存（7天）\n└── \u003capp_name\u003e.conf                    # 自定义模式配置文件\n\n/usr/local/lib/flutter-cjk/            # SO 文件本地缓存\n└── libflutter_linux_gtk.so.X.Y.Z      # 下载的 SO 文件\n\n/etc/systemd/system/\n└── flutter-font-fix.service           # 系统启动服务\n\n/etc/bash_completion.d/\n└── flutter-font-fix                   # Tab 补全脚本\n\n/usr/local/bin/\n└── flutter-font-fix                   # 主执行脚本\n\n\u003crepository\u003e/lib/                      # GitHub 仓库 SO 文件库\n└── libflutter_linux_gtk.so.X.Y.Z      # 预编译的 SO 文件（30-40MB）\n```\n\n### 配置文件说明\n\n**ubuntu.conf** - 应用配置列表（新格式）\n```\nsnap-store|so              # SO 引擎替换\ndesktop-security-center|font   # 字体映射\nrustdesk|so                # 非 Snap 应用也记录在此\nold-app                    # 旧格式（兼容）\n```\n\n**flutter.engine.hash.version** - Flutter Engine Hash→版本缓存\n```bash\n# 格式: hash | version\n2c9bc1e4b1... | 3.38.1\na7f8e9d2c3... | 3.24.3\n```\n\u003e 缓存有效期 7 天，避免重复查询 Flutter GitHub 仓库\n\n**\\\u003capp\\\u003e.conf** - 自定义模式配置示例\n```bash\n# Flutter Font Fix - Custom Font Configuration\n# App: snap-store\n# Generated: 2025-12-20 10:30:45\n\n/snap/snap-store/current/fonts/Ubuntu-R.ttf|/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc\n/snap/snap-store/current/fonts/Ubuntu-B.ttf|/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc\n```\n\n---\n\n## 🔍 技术细节\n\n### 实现原理\n1. **Hash 精确检测**：从 SO 文件提取 Flutter Engine Hash（40 位），查询 Flutter GitHub 建立版本对照表（7 天缓存）\n2. **双源查找**：本地优先，精确版本时跳过线上查询，自动下载在线版本（30-40MB，进度条）\n3. **智能替换**：\n   - Snap 应用：`mount --bind` 替换（仅精确版本）\n   - 非 Snap 应用：直接替换系统 SO（支持相似版本，自动备份 `.bak`）\n4. **字体映射兜底**：无匹配 SO 时自动回退到 Noto CJK 字体映射\n5. **开机自启**：Systemd 服务 `After=snapd.service` 确保 Snap 就绪后执行\n\n### 检测流程示例\n```bash\n# 1. 提取 Hash\nstrings libflutter_linux_gtk.so | grep -E '^[0-9a-f]{40}$'\n# → 2c9bc1e4b1a7f8e9d2c3456789abcdef01234567\n\n# 2. 匹配版本（查询 Flutter GitHub，7天缓存）\n# → 3.38.1\n\n# 3. 查找/下载 SO\n# 本地: /usr/local/lib/flutter-cjk/libflutter_linux_gtk.so.3.38.1\n# 线上: https://raw.githubusercontent.com/.../libflutter_linux_gtk.so.3.38.1\n```\n\n### 字重映射关系\n\n字体映射方案（兜底）：\n```\nUbuntu-R.ttf/RI  → NotoSansCJK-Regular.ttc\nUbuntu-L.ttf/LI  → NotoSansCJK-Light.ttc\nUbuntu-M.ttf/MI  → NotoSansCJK-Medium.ttc\nUbuntu-B.ttf/BI  → NotoSansCJK-Bold.ttc\n```\n\n自定义模式（`-c`）可自由选择映射关系。\n\n### Systemd 服务配置\n```ini\n[Unit]\nDescription=Flutter Font Auto-Mount Service (System Level)\nAfter=snapd.service\nRequires=snapd.service\nConditionPathExists=/etc/flutter-cjk\n\n[Service]\nType=oneshot\nExecStartPre=/bin/sleep 3\nExecStart=/usr/local/bin/flutter-font-fix --startup\nRemainAfterExit=yes\n\n[Install]\nWantedBy=multi-user.target\n```\n\n---\n\n## 🤔 常见问题\n\n**Q: -a 模式和 -e 模式有什么区别？**\n- **-a 模式**：针对 Snap 应用，仅使用精确版本的 SO 文件，未找到时回退到字体映射\n- **-e 模式**：针对非 Snap 应用（如 rustdesk），支持精确版本和相似版本选择（如 3.24.3 用于 3.24.5）\n\n**Q: 什么是相似版本？**\n- 相似版本指主版本号相同的 Flutter 版本（如 3.24.1、3.24.3、3.24.5 都属于 3.24.x）\n- 在 `-e` 模式下，如果找不到精确版本，会提示选择相似版本\n- Snap 应用（`-a` 模式）不使用相似版本，保证稳定性\n\n**Q: 如何恢复原始 SO 文件？**\n```bash\n# 非 Snap 应用（-e 模式）会自动备份\nsudo cp /path/to/libflutter_linux_gtk.so.bak /path/to/libflutter_linux_gtk.so\n\n# Snap 应用（-a 模式）使用 mount，直接卸载即可\nsudo flutter-font-fix -r snap-store\n```\n\n**Q: 修复后需要重启应用吗？**\n- 通常不需要。映射立即生效，但部分应用可能需要重启以重新加载字体缓存\n\n**Q: 会影响系统其他应用吗？**\n- 不会。Snap 应用的 SO 替换仅作用于该应用内部\n- 非 Snap 应用会修改系统目录中的 SO，但会自动备份原文件\n\n**Q: 如何验证修复是否成功？**\n```bash\n# 检查挂载状态（Snap 应用）\nmount | grep flutter\n\n# 查看配置\nflutter-font-fix -d\n\n# 检查 SO 文件（非 Snap 应用）\nldd /usr/bin/rustdesk | grep libflutter_linux_gtk.so\nls -la /path/to/libflutter_linux_gtk.so*\n\n# 重启应用并观察中文显示\n```\n\n**Q: 缓存文件在哪里？**\n```bash\n# Hash→版本对照表缓存（7天有效期）\n/etc/flutter-cjk/flutter.engine.hash.version\n\n# 下载的 SO 文件缓存\n/usr/local/lib/flutter-cjk/libflutter_linux_gtk.so.*\n```\n\n---\n\n## 🛠️ 故障排查\n\n### 问题：修复后仍显示方框\n1. 检查 Noto 字体是否已安装：\n   ```bash\n   dpkg -l | grep fonts-noto-cjk\n   ```\n2. 验证挂载点是否生效：\n   ```bash\n   mount | grep \u003capp_name\u003e\n   ```\n3. 尝试重启应用或重新映射\n\n### 问题：开机后映射失效\n1. 检查服务状态：\n   ```bash\n   sudo systemctl status flutter-font-fix.service\n   ```\n2. 查看服务日志：\n   ```bash\n   sudo journalctl -u flutter-font-fix.service\n   ```\n3. 手动触发服务：\n   ```bash\n   sudo systemctl start flutter-font-fix.service\n   ```\n\n### 问题：Tab 补全不生效\n1. 重新加载补全脚本：\n   ```bash\n   source /etc/bash_completion.d/flutter-font-fix\n   ```\n2. 或重新安装：\n   ```bash\n   sudo flutter-font-fix -i\n   ```\n\n---\n\n## 📄 开源协议\n\n[MIT License](LICENSE)\n\n---\n\n## 🙏 致谢\n\n本项目的核心问题研究和解决方案由 **Gemini 3** 深度分析提供，代码实现使用 **VS Code + GitHub Copilot + Claude Sonnet 4.5** 协同完成。\n\n感谢社区中关于 Snap 字体问题的讨论和相关技术资料。\n\n---\n\n## 📮 反馈与贡献\n\n欢迎通过 [Issues](https://github.com/krystic/flutter-arm-cjk-fix/issues) 报告问题或提出建议。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrystic%2Fflutter-arm-cjk-fix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrystic%2Fflutter-arm-cjk-fix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrystic%2Fflutter-arm-cjk-fix/lists"}