跳到主内容

v0.26.0 版本说明

EnerOS v0.26.0 版本说明

发布日期:2025-10-05 版本代号:Babel Git Tag:v0.26.0 支持状态:稳定(Stable) Crate 总数:67(新增 3 个) 测试用例数:8550+(新增 450+)

概述

EnerOS v0.26.0「Babel」是国际化(i18n)专项版本,使 EnerOS 能够服务全球不同地区的电力运营商。电力系统虽遵循通用的物理定律,但不同国家/地区在语言、单位制、电压等级、频率标准、监管要求、时区等方面存在显著差异。v0.26.0 将这些区域差异抽象为可配置的本地化层,使同一套内核代码能够无缝适配不同地区。

本版本引入了五大核心能力:国际化框架(i18n Framework)、多语言支持(Multi-language Support)、区域适配(Regional Adaptation)、时区处理(Timezone Handling)、本地化文档(Localized Documentation)。所有面向用户的字符串、日期、数值、单位均通过本地化层渲染,内核逻辑保持语言无关。

设计哲学上,v0.26.0 坚持「内核语言无关」——内核与智能体的业务逻辑不依赖任何特定语言;「区域配置驱动」——区域差异通过配置文件而非代码分支处理;「时区一等公民」——所有时间戳内部统一使用 UTC,仅在展示与交互时转换为本地时区。

关键数据

指标数值说明
支持语言12 种中英日韩德法等
支持时区全部 IANA384 个
本地化条目8000+UI 字符串
区域配置集8 个主要市场
新增 Crate3i18n 相关
新增测试450+含本地化测试

新特性

1. 国际化框架

引入 eneros-i18n Crate,提供统一的国际化框架。基于 Fluent(Project Fluent)实现,支持复数、性别、上下文等复杂语法。

基础用法

use eneros_i18n::{I18n, Locale};

let i18n = I18n::new()
    .locale(Locale::zh_CN())
    .fallback(Locale::en_US())
    .load_dir("locales/")?;

// 翻译
let msg = i18n.t("alarm.voltage-high", |b| b
    .arg("bus", "42")
    .arg("voltage", "1.08"))?;
// 中文: "母线 42 电压 1.08pu 越上限"
// 英文: "Bus 42 voltage 1.08pu exceeds upper limit"

复数处理

// 复数形式自动适配
let msg = i18n.t("alarm.devices-offline", |b| b
    .arg("count", 3))?;
// 中文: "3 台设备离线"
// 英文: "3 devices offline"
// 俄语: "3 устройства не в сети"(俄语有3种复数形式)

支持语言

语言代码完成度主要市场
简体中文zh-CN100%中国大陆
英语en-US100%北美
英语en-GB95%英国
日语ja-JP92%日本
韩语ko-KR88%韩国
德语de-DE90%德国
法语fr-FR85%法国
西班牙语es-ES82%西班牙/拉美
葡萄牙语pt-BR80%巴西
俄语ru-RU78%俄罗斯
阿拉伯语ar-SA65%中东
印地语hi-IN60%印度

2. 多语言支持

引入 eneros-i18n-mo(Multi-language Orchestrator),支持运行时动态切换语言,无需重启。

动态切换

use eneros_i18n_mo::LanguageManager;

let lang_mgr = LanguageManager::new(&i18n);

// 按用户偏好切换
lang_mgr.set_locale(user_id, Locale::ja_JP()).await?;

// 按地区自动检测
let detected = lang_mgr.detect_from_region("JP")?;
lang_mgr.set_default(detected)?;

智能体多语言

// 智能体按用户语言响应
let agent = Agent::new("dispatch-assistant")
    .language(LanguagePolicy::FollowUser);

// 中文用户提问
let reply = agent.chat("母线 42 电压为什么偏高?").await?;
// 中文回复

// 英文用户提问
let reply = agent.chat("Why is bus 42 voltage high?").await?;
// 英文回复

翻译流程

阶段说明工具
提取从代码提取待翻译字符串xtr
翻译人工/机器翻译Crowdin
编译编译为 .ftl 文件fluent
加载运行时加载eneros-i18n
验证检查缺失/冲突自研工具

3. 区域适配

引入 eneros-i18n-region Crate,提供区域差异适配。不同地区的电压等级、频率、单位制、保护配置均通过区域配置集管理。

区域配置

use eneros_i18n_region::{Region, RegionConfig};

let region = Region::from_code("CN")
    .config(RegionConfig {
        frequency_hz: 50.0,
        voltage_levels: vec![110, 220, 500, 750, 1000],
        voltage_unit: VoltageUnit::KV,
        power_unit: PowerUnit::MW,
        coordinate_system: CoordSystem::CGCS2000,
        standard: Standard::GB,
    });

manager.set_region(region)?;

区域差异表

区域频率(Hz)电压等级(kV)单位制坐标系标准
中国50110/220/500/750/1000公制CGCS2000GB
美国60115/230/500/765英制+公制NAD83IEEE/NERC
欧洲50110/220/380公制ETRS89EN/IEC
日本50/6066/154/275/500公制JGD2011JIS
巴西60138/230/500/750公制SIRGAS2000ABNT

单位转换

use eneros_i18n_region::units::{Voltage, Power, Energy};

// 自动按区域转换
let v = Voltage::from_kv(220.0);
println!("{}", v.display(&region));  // CN: "220.0 kV"

let p = Power::from_mw(500.0);
println!("{}", p.display(&region));  // US: "500 MW"

let e = Energy::from_kwh(1000.0);
println!("{}", e.display(&region));  // CN: "1000 kWh"

4. 时区处理

引入 eneros-i18n-tz Crate,提供完善的时区处理。所有内部时间戳统一使用 UTC 纳秒精度,仅在展示与交互时转换为本地时区。

时区转换

use eneros_i18n_tz::{Timestamp, TimeZone};

// 内部存储:UTC 纳秒
let event_time = Timestamp::now_utc();

// 展示:按用户时区
let tz = TimeZone::from_iana("Asia/Shanghai");
let local = event_time.to_local(&tz);
println!("事件时间: {}", local.format("%Y-%m-%d %H:%M:%S %Z"));
// "事件时间: 2025-10-05 14:30:00 CST"

// 跨时区对比
let ny = TimeZone::from_iana("America/New_York");
println!("纽约时间: {}", event_time.to_local(&ny).format(...));
// "纽约时间: 2025-10-05 02:30:00 EDT"

跨时区调度

// 跨时区运维编排
let maintenance_window = MaintenanceWindow::new()
    .start("2025-10-05 02:00:00", TimeZone::America/New_York)
    .duration(Duration::hours(4));

// 自动转换为各节点本地时间
for node in cluster.nodes() {
    let local_start = maintenance_window.start_at(&node.timezone);
    println!("{}: 本地开始 {}", node.id, local_start);
}

时区处理规则

场景处理方式说明
内部存储UTC 纳秒统一基准
日志UTC便于排序
UI 展示用户时区本地友好
调度区域时区按业务
告警用户时区即时通知
报表区域时区合规要求

5. 本地化文档

引入 eneros-i18n-docs Crate,提供文档本地化能力。技术文档、运维手册、API 参考均支持多语言版本。

文档构建

use eneros_i18n_docs::{DocBuilder, Locale};

let builder = DocBuilder::new()
    .source("docs/")
    .output("dist/docs/")
    .locales(vec![Locale::zh_CN(), Locale::en_US(), Locale::ja_JP()]);

builder.build().await?;

文档翻译状态

文档类型zh-CNen-USja-JP其他
快速开始100%100%95%70%
用户指南100%95%80%60%
API 参考100%100%60%30%
运维手册100%85%50%20%
最佳实践90%80%40%15%

改进

  • 字符串提取:新增 eneros-i18n-extract 工具,自动提取代码中的待翻译字符串
  • RTL 支持:阿拉伯语等从右向左书写语言获得完整 UI 适配
  • 日期格式:支持各区域习惯的日期格式(YYYY-MM-DD / MM/DD/YYYY / DD/MM/YYYY)
  • 数字格式:支持千分位、小数点符号的区域差异(1,000.00 / 1.000,00)

Bug 修复

  • 修复 eneros-i18n 在 Fluent 消息嵌套引用时的解析错误(#2605)
  • 修复 eneros-i18n-tz 在夏令时切换边界的时间偏移问题(#2610)
  • 修复 eneros-i18n-region 单位转换在英制/公制混合时的精度损失(#2615)
  • 修复 eneros-i18n-docs 在构建多语言版本时的链接错误(#2620)

破坏性变更

  • Timestamp::now:重命名为 Timestamp::now_utc,强调 UTC 语义
  • format! 调用:所有面向用户的字符串必须通过 i18n.t() 翻译,禁止硬编码

升级指南

  1. 执行 cargo update -p eneros-i18n
  2. Timestamp::now 调用更新为 Timestamp::now_utc
  3. 将硬编码的面向用户字符串迁移至 .ftl 文件
  4. 参考 docs/migration/v0.26.0.md 获取详细迁移步骤