【免费下载链接】pomotroid:tomato: Simple and visually-pleasing Pomodoro timer项目地址https://gitcode.com/gh_mirrors/po/pomotroid点击查看免费下载本文以 Pomotroid 新增土耳其语tr支持这一真实变更为主线讲解其基于 Paraglide JS v2 的国际化i18n架构从消息文件结构、locale 注册、语言解析与即时切换到桌面通知与 Tooltip 的翻译覆盖完整演示如何在零 Rust 改动的前提下为一个 Tauri SvelteKit 桌面应用接入新语言。为什么新增一个 locale 如此轻在 Pomotroid 中添加土耳其语Turkish不涉及任何架构改动。原因在于其国际化完全建立在 Paraglide JS 之上所有面向用户的字符串都集中存放在src/messages/locale.json消息文件中构建期由 Paraglide 扫描 project.inlang/settings.json 中声明的locales数组为每个语言生成类型安全的m.key()消息函数前端通过m.*()调用读取字符串界面、通知、Tooltip 全部走同一条链路。因此新增语言本质上是加一个文件 注册一个条目 在下拉菜单里加一项正如 proposal.md 所述无 Rust 改动、无数据库迁移、无新增依赖。一、8 语言架构从 7 到 8 的版本演进本次变更将启动时支持的语言从 7 种扩展到 8 种。完整的 locale 集合定义在 project.inlang/settings.json{ $schema: https://inlang.com/schema/project-settings, baseLocale: en, locales: [en, es, fr, de, ja, zh, pt, tr], modules: [ https://cdn.jsdelivr.net/npm/inlang/plugin-message-format4/dist/index.js, https://cdn.jsdelivr.net/npm/inlang/plugin-m-function-matcher2/dist/index.js ], plugin.inlang.messageFormat: { pathPattern: ./src/messages/{locale}.json } }要点解读baseLocale: en是基准语言也是缺失键时的回退语言locales数组按en, es, fr, de, ja, zh, pt, tr顺序声明 8 种语言英语、西班牙语、法语、德语、日语、简体中文、葡萄牙语、土耳其语pathPattern定义了消息文件的存放模式./src/messages/{locale}.jsonParaglide 据此在构建期发现并编译每个语言的文件模块inlang/plugin-message-format负责 JSON 消息格式的解析inlang/plugin-m-function-matcher负责消息函数的匹配。启动时npm run paraglide:compile即paraglide-js compile --project ./project.inlang --outdir ./src/paraglide会把上述配置编译为src/paraglide下的运行时与消息模块前端通过import * as m from $paraglide/messages.js使用。类型安全由 Paraglide 自动保证一旦某消息键在en.json中不存在TypeScript 编译期即报错防止界面引用漂移。二、消息文件109 个键的完整翻译新增的 src/messages/tr.json 包含与 src/messages/en.json 完全对齐的109 个翻译键覆盖五大功能面功能面典型键英文示例土耳其语示例计时器与导航nav_timer、round_label_work、timer_slider_roundsFocusOdaklanma外观与设置appearance_mode_auto、system_group_languageAutoOtomatik通知与声音notification_work_title、notif_alert_workBreak over — focus time!Mola bitti — odaklanma zamanı!快捷键shortcuts_toggle_timer、shortcuts_local_muteToggle TimerZamanlayıcıyı Aç/Kapat统计与 Tooltipstats_today、tooltip_resetOpen Statisticsİstatistikleri aç以几组真实键为例可以看出翻译不仅是直译还适配了土耳其语习惯timer_session_round: tur {n}, system_toggle_websocket_desc: Harici entegrasyonlar için yerel bir WebSocket uç noktası sun (port {port})., shortcuts_accessibility_notice: Genel kısayollar macOSta Erişilebilirlik iznini gerektirir. Sistem Ayarları → Gizlilik ve Güvenlik → Erişilebilirlik bölümünde Pomotroidi etkinleştirin.注意占位符的保留{n}、{port}、{version}等插值参数必须原样保留在翻译文本中因为运行时 Paraglide 会按键注入动态值。这在about_update_installInstall v{version} — app will restart等键中尤其关键。非英语语言文件必须包含en.json中每一个键。这是 localization spec 的硬性要求非英语文件加载后en.json中所有键都应有对应条目若活动语言的某个键缺失则显示英文回退字符串。这一约束确保任何语言都不会出现空白界面。三、语言解析与回退逻辑auto、前缀匹配与 en 兜底language设置默认值为auto见 src-tauri/src/settings/defaults.rs即默认跟随系统。解析逻辑集中在 src/lib/utils/locale.tsexport function resolveLocale(language: string): SupportedLocale { const tag language auto ? navigator.language : language; return matchLocale(tag); } function matchLocale(tag: string): SupportedLocale { // Exact match first. if ((locales as readonly string[]).includes(tag)) { return tag as SupportedLocale; } // Prefix match: de-AT → de. const prefix tag.split(-)[0]; if ((locales as readonly string[]).includes(prefix)) { return prefix as SupportedLocale; } return baseLocale as SupportedLocale; }解析规则可以归纳为三级匹配精确匹配navigator.language或用户指定标签恰好等于某个受支持 locale如fr直接命中前缀匹配带地区限定符的语言代码如de-AT取-前的语言部分de匹配回退完全无匹配时回退到baseLocaleen。有趣的是zh-CN这类标签会命中前缀zh与 spec 中的旧场景略有出入实际以 locale.ts 的当前实现为准。这套逻辑对土耳其语同样生效tr精确匹配、tr-TR前缀匹配、其他语言回退英文。SupportedLocale类型直接取自 Paraglide 编译产物的locales数组(typeof locales)[number]因此类型层面与settings.json中声明的 locale 集合天然同步——这正是加一个 locale 不需要改类型定义的底层原因。四、即时切换语言下拉与跨窗口热更新语言选择器位于Settings → System → Language。在 SystemSection.svelte 中定义的语言选项如下const LANGUAGES [ { value: auto, label: Auto }, { value: en, label: English }, { value: es, label: Español }, { value: fr, label: Français }, { value: de, label: Deutsch }, { value: ja, label: 日本語 }, { value: zh, label: 中文 }, { value: pt, label: Português }, { value: tr, label: Türkçe }, ];注意两点设计细节每个选项的label用该语言的原生名称展示土耳其语显示为Türkçe便于母语用户识别value与数据库存储值对应auto或 locale 标签。用户选择后触发 selectLanguageasync function selectLanguage(value: string) { langOpen false; const updated await setSetting(language, value); settings.set(updated); setLocale(value); }调用链为setSetting(language, tr)→ Tauri 命令settings_set持久化到 SQLite → Rust 端发出settings:changed事件见 commands.rs→ 各窗口监听事件后重新调用setLocale()。这一机制同时作用于主计时器窗口、设置窗口与统计窗口page.svelte、settings/page.svelte、stats/page.svelte 中均有onSettingsChanged→setLocale(updated.language)的订阅逻辑因此切换语言无需重启应用。语言切换的响应式核心在 src/lib/locale.svelte.tslet currentLocale: SupportedLocale $state(baseLocale as SupportedLocale); // Override Paraglides getLocale so that every m.*() call reads from our // reactive $state instead of its internal plain-JS variable. overwriteGetLocale(() currentLocale); export function setLocale(language: string): void { const resolved resolveLocale(language) as SupportedLocale; currentLocale resolved; info([locale] locale set to ${resolved}).catch(() {}); }这是 Svelte 5 rune$state与 Paraglide 的巧妙结合通过overwriteGetLocale让所有m.*()调用读取响应式状态任何模板表达式中读取m.xxx()都会建立依赖跟踪currentLocale一旦变化所有界面字符串自动重渲染。这也是两个窗口同时更新的实现基础——每个窗口各自持有setLocale通过settings:changed事件驱动。五、翻译覆盖延伸桌面通知与 Tooltip桌面通知通知字符串的翻译完全在前端完成。在 Timer.svelte 的onRoundChange回调中if (snap.round_type work) { const afterBreak snap.previous_round_type short-break || snap.previous_round_type long-break; title afterBreak ? m.notification_work_title() : m.notification_work_start_title(); body afterBreak ? m.notification_work_body() : m.notification_work_start_body(); } // ... notificationShow(title, body).catch(() {});前端根据轮次类型选择已翻译的标题与正文再通过notificationShow(title, body)命令传给 Rust。Rust 端 notifications/mod.rs 完全不参与字符串构造保持 locale 无关Linux 下通过notify-send子进程发送避免 D-Bus 会话总线连接问题macOS / Windows 下使用tauri-plugin-notification。因此当用户选择土耳其语时通知会显示如 Mola bitti — odaklanma zamanı! 这样的土耳其语内容。Tooltip 提示所有 Tooltip 的 i18n 键也必须在每个语言文件中存在可机器翻译。tr.json中覆盖了完整的 Tooltip 键集包括tooltip_settings→ Ayarları açtooltip_restart_round→ Mevcut turu baştan başlat.tooltip_reset→ Zamanlayıcıyı ilk çalışma turuna sıfırla. Mevcut oturum ilerlemesi silinecek.tooltip_verbose_logging→ 包含完整诊断日志指引tooltip_websocket→ WebSocket 服务器功能说明以及tooltip_dial_countdown、tooltip_auto_start_work、tooltip_auto_start_break等值得一提的是system_tray_gnome_hint它是 Linux 专属的TooltipInfo图标复用的既有键早于本次变更无需新增键tr.json中同样提供了土耳其语翻译GNOMEda sistem tepsisi simgeleri AppIndicator eklentisini gerektirir…。六、本次变更的影响面清单按 proposal.md 的 Impact 总结变更只触及三个文件文件变更内容src/messages/tr.json新增文件109 个已翻译键project.inlang/settings.jsonlocales数组加入trSystemSection.svelte语言下拉框加入 Türkçe 选项无Rust 代码改动、无数据库迁移、无新增依赖。新增语言时的标准步骤可归纳为复制src/messages/en.json为src/messages/locale.json翻译全部键保留{n}、{port}、{version}等占位符在project.inlang/settings.json的locales数组追加新标签在SystemSection.svelte的LANGUAGES数组中增加{ value: locale, label: 原生语言名 }运行npm run paraglide:compile重新生成类型安全的消息模块TypeScript 编译器会立即校验键的完整性。由于SupportedLocale类型由编译产物推导、语言解析走通用前缀匹配、跨窗口热更新走settings:changed事件这套流程对任何后续新语言包括未来可能的阿拉伯语、韩语等完全通用无需为单一语言编写任何特殊代码。这正是 Paraglide 消息目录 类型安全访问 响应式运行时这一组合在桌面应用中的典型落地范式。赞分享【免费下载链接】pomotroid:tomato: Simple and visually-pleasing Pomodoro timer项目地址https://gitcode.com/gh_mirrors/po/pomotroid点击查看免费下载相关推荐Pomotroid 土耳其语本地化实战基于 Paraglide JS 的 tr 语言包接入全流程Pomotroid 土耳其语本地化实战基于 Paraglide JS 的 tr 语言包接入全流程 本文以 Pomotroid 开源仓库中 土耳其语支持变更设计Pomotroid 多语言化实战基于 Paraglide JS 的 Tauri SvelteKit 国际化架构全解析Pomotroid 多语言化实战基于 Paraglide JS 的 Tauri SvelteKit 国际化架构全解析 Pomotroid 是一款基于 TaPomotroid 多语言支持i18n全解析基于 Paraglide JS 的 Tauri 桌面应用本地化实践Pomotroid 多语言支持i18n全解析基于 Paraglide JS 的 Tauri 桌面应用本地化实践 Pomotroid 是一个基于 Tauri创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考