refactor(i18n): extract op-i18n crate (with Locale) from openpencil-shell-core
This commit is contained in:
parent
1ef513d5a6
commit
08686c3b95
5
Cargo.lock
generated
5
Cargo.lock
generated
|
|
@ -2274,6 +2274,10 @@ version = "1.21.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||
|
||||
[[package]]
|
||||
name = "op-i18n"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "openpencil-desktop"
|
||||
version = "0.1.0"
|
||||
|
|
@ -2307,6 +2311,7 @@ dependencies = [
|
|||
"bitflags 2.11.1",
|
||||
"glam",
|
||||
"jian-core",
|
||||
"op-i18n",
|
||||
"serde",
|
||||
"thiserror 1.0.69",
|
||||
"tracing",
|
||||
|
|
|
|||
9
crates/op-i18n/Cargo.toml
Normal file
9
crates/op-i18n/Cargo.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "op-i18n"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
license.workspace = true
|
||||
description = "OpenPencil i18n — Locale enum + 15-locale string tables"
|
||||
|
||||
[dependencies]
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
//! (`common.untitled`, `rightPanel.design`, `layout.flexLayout`,
|
||||
//! …) so cross-walking strings between TS and Rust is mechanical.
|
||||
|
||||
use crate::document::Locale;
|
||||
use crate::Locale;
|
||||
|
||||
mod de;
|
||||
mod en;
|
||||
5
crates/op-i18n/src/lib.rs
Normal file
5
crates/op-i18n/src/lib.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
//! OpenPencil i18n — Locale + 15-locale string tables.
|
||||
mod i18n;
|
||||
mod locale;
|
||||
pub use i18n::*;
|
||||
pub use locale::Locale;
|
||||
70
crates/op-i18n/src/locale.rs
Normal file
70
crates/op-i18n/src/locale.rs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/// UI locale — full set of 15 mirrored from
|
||||
/// `apps/web/src/i18n/locales/`. ZhCn + EnUs ship with complete
|
||||
/// chrome translation tables; the rest fall through to EnUs
|
||||
/// (visually obvious that translation is pending).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Locale {
|
||||
EnUs,
|
||||
ZhCn,
|
||||
ZhTw,
|
||||
Ja,
|
||||
Ko,
|
||||
Fr,
|
||||
Es,
|
||||
De,
|
||||
Pt,
|
||||
Ru,
|
||||
Hi,
|
||||
Tr,
|
||||
Th,
|
||||
Vi,
|
||||
Id,
|
||||
}
|
||||
|
||||
impl Locale {
|
||||
/// All locales in TopBar dropdown order — matches TS app.
|
||||
pub const ALL: [Locale; 15] = [
|
||||
Locale::EnUs,
|
||||
Locale::ZhCn,
|
||||
Locale::ZhTw,
|
||||
Locale::Ja,
|
||||
Locale::Ko,
|
||||
Locale::Fr,
|
||||
Locale::Es,
|
||||
Locale::De,
|
||||
Locale::Pt,
|
||||
Locale::Ru,
|
||||
Locale::Hi,
|
||||
Locale::Tr,
|
||||
Locale::Th,
|
||||
Locale::Vi,
|
||||
Locale::Id,
|
||||
];
|
||||
|
||||
/// Cycle to the next locale (round-trips through `ALL`).
|
||||
pub fn next(self) -> Self {
|
||||
let i = Self::ALL.iter().position(|&l| l == self).unwrap_or(0);
|
||||
Self::ALL[(i + 1) % Self::ALL.len()]
|
||||
}
|
||||
|
||||
/// Native-script display name (matches the TS dropdown).
|
||||
pub fn display_name(self) -> &'static str {
|
||||
match self {
|
||||
Locale::EnUs => "English",
|
||||
Locale::ZhCn => "简体中文",
|
||||
Locale::ZhTw => "繁體中文",
|
||||
Locale::Ja => "日本語",
|
||||
Locale::Ko => "한국어",
|
||||
Locale::Fr => "Français",
|
||||
Locale::Es => "Español",
|
||||
Locale::De => "Deutsch",
|
||||
Locale::Pt => "Português",
|
||||
Locale::Ru => "Русский",
|
||||
Locale::Hi => "हिन्दी",
|
||||
Locale::Tr => "Türkçe",
|
||||
Locale::Th => "ไทย",
|
||||
Locale::Vi => "Tiếng Việt",
|
||||
Locale::Id => "Bahasa Indonesia",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,11 @@ accesskit = "0.24"
|
|||
# cargo silently picking a wrong version under a different workspace context.
|
||||
jian-core = { path = "../../vendor/jian/crates/jian-core", version = "0.0.1" }
|
||||
|
||||
# Phase 3 strangler reorg: i18n (Locale + 15-locale string tables) extracted
|
||||
# into op-i18n; shell-core re-exports it as `i18n` so downstream callers keep
|
||||
# resolving `crate::i18n::*` / `crate::document::Locale` unchanged.
|
||||
op-i18n = { path = "../op-i18n" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
serde = ["dep:serde"]
|
||||
|
|
|
|||
|
|
@ -677,76 +677,10 @@ impl ThemeMode {
|
|||
}
|
||||
}
|
||||
|
||||
/// UI locale — full set of 15 mirrored from
|
||||
/// `apps/web/src/i18n/locales/`. ZhCn + EnUs ship with complete
|
||||
/// chrome translation tables; the rest fall through to EnUs
|
||||
/// (visually obvious that translation is pending).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Locale {
|
||||
EnUs,
|
||||
ZhCn,
|
||||
ZhTw,
|
||||
Ja,
|
||||
Ko,
|
||||
Fr,
|
||||
Es,
|
||||
De,
|
||||
Pt,
|
||||
Ru,
|
||||
Hi,
|
||||
Tr,
|
||||
Th,
|
||||
Vi,
|
||||
Id,
|
||||
}
|
||||
|
||||
impl Locale {
|
||||
/// All locales in TopBar dropdown order — matches TS app.
|
||||
pub const ALL: [Locale; 15] = [
|
||||
Locale::EnUs,
|
||||
Locale::ZhCn,
|
||||
Locale::ZhTw,
|
||||
Locale::Ja,
|
||||
Locale::Ko,
|
||||
Locale::Fr,
|
||||
Locale::Es,
|
||||
Locale::De,
|
||||
Locale::Pt,
|
||||
Locale::Ru,
|
||||
Locale::Hi,
|
||||
Locale::Tr,
|
||||
Locale::Th,
|
||||
Locale::Vi,
|
||||
Locale::Id,
|
||||
];
|
||||
|
||||
/// Cycle to the next locale (round-trips through `ALL`).
|
||||
pub fn next(self) -> Self {
|
||||
let i = Self::ALL.iter().position(|&l| l == self).unwrap_or(0);
|
||||
Self::ALL[(i + 1) % Self::ALL.len()]
|
||||
}
|
||||
|
||||
/// Native-script display name (matches the TS dropdown).
|
||||
pub fn display_name(self) -> &'static str {
|
||||
match self {
|
||||
Locale::EnUs => "English",
|
||||
Locale::ZhCn => "简体中文",
|
||||
Locale::ZhTw => "繁體中文",
|
||||
Locale::Ja => "日本語",
|
||||
Locale::Ko => "한국어",
|
||||
Locale::Fr => "Français",
|
||||
Locale::Es => "Español",
|
||||
Locale::De => "Deutsch",
|
||||
Locale::Pt => "Português",
|
||||
Locale::Ru => "Русский",
|
||||
Locale::Hi => "हिन्दी",
|
||||
Locale::Tr => "Türkçe",
|
||||
Locale::Th => "ไทย",
|
||||
Locale::Vi => "Tiếng Việt",
|
||||
Locale::Id => "Bahasa Indonesia",
|
||||
}
|
||||
}
|
||||
}
|
||||
// Phase 3 strangler reorg: the `Locale` enum + its impls moved into the
|
||||
// `op-i18n` crate (alongside the 15-locale string tables). Re-exported here
|
||||
// so existing `document::Locale` / `crate::document::Locale` paths resolve.
|
||||
pub use op_i18n::Locale;
|
||||
|
||||
/// Identifier for a property-panel input row.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ pub mod chat_provider;
|
|||
pub mod codegen;
|
||||
pub mod document;
|
||||
pub mod figma;
|
||||
pub mod i18n;
|
||||
// Phase 3 strangler reorg: i18n extracted into the op-i18n crate. Re-exported
|
||||
// as `i18n` so `crate::i18n::translate` / `crate::i18n::Locale` paths still resolve.
|
||||
pub use op_i18n as i18n;
|
||||
pub mod jian;
|
||||
pub mod mcp;
|
||||
#[cfg(test)] mod mcp_tests;
|
||||
|
|
|
|||
Loading…
Reference in a new issue