Merge pull request #571 from seldoms/i18n/chinese-translations
This commit is contained in:
commit
5de747735e
|
|
@ -54,13 +54,51 @@ fn system_language() -> &'static str {
|
|||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
static LANGUAGE: std::sync::OnceLock<&'static str> = std::sync::OnceLock::new();
|
||||
LANGUAGE.get_or_init(|| supported(sys_locale::get_locale().as_deref()))
|
||||
LANGUAGE.get_or_init(|| {
|
||||
let locale = sys_locale::get_locale();
|
||||
// `C` / `POSIX` (and variants like `C.UTF-8`) mean "no particular locale": don't force
|
||||
// English, ask the macOS preferred-languages list instead.
|
||||
if locale.as_deref().is_some_and(is_c_locale) {
|
||||
#[cfg(target_os = "macos")]
|
||||
if let Some(l) = macos_preferred_language() {
|
||||
return l;
|
||||
}
|
||||
return "en";
|
||||
}
|
||||
supported(locale.as_deref())
|
||||
})
|
||||
}
|
||||
// No system locale in the browser build: English.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
supported(None)
|
||||
}
|
||||
|
||||
/// True when `locale` names the generic `C` / `POSIX` locale (or a variant like `C.UTF-8`).
|
||||
fn is_c_locale(locale: &str) -> bool {
|
||||
let base = locale.split(['.', '@']).next().unwrap_or("").to_ascii_lowercase();
|
||||
matches!(base.as_str(), "c" | "posix")
|
||||
}
|
||||
|
||||
/// The first supported language in the macOS `defaults read -g AppleLanguages` list.
|
||||
#[cfg(target_os = "macos")]
|
||||
fn macos_preferred_language() -> Option<&'static str> {
|
||||
let out = std::process::Command::new("/usr/bin/defaults")
|
||||
.args(["read", "-g", "AppleLanguages"])
|
||||
.output()
|
||||
.ok()?;
|
||||
if !out.status.success() {
|
||||
return None;
|
||||
}
|
||||
String::from_utf8_lossy(&out.stdout)
|
||||
.split(['(', ')', ',', '"', '\n'])
|
||||
.map(str::trim)
|
||||
.filter(|s| !s.is_empty())
|
||||
.find_map(|tag| {
|
||||
let lang = supported(Some(tag));
|
||||
(lang != "en").then_some(lang)
|
||||
})
|
||||
}
|
||||
|
||||
/// The language EffectCraft shows for a BCP 47 locale (`ja-JP` → `ja`, `zh-Hans-CN` → `zh-hans`,
|
||||
/// `zh-TW` → `zh-hant`, `uk-UA` → `uk`).
|
||||
fn supported(locale: Option<&str>) -> &'static str {
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
|||
("About EffectCraft", "关于 EffectCraft"),
|
||||
("About...", "关于..."),
|
||||
("Active Camera", "活动摄像机"),
|
||||
("Alpha", "Alpha"),
|
||||
("Adapt Feature On Every Frame", "每帧都适应特征"),
|
||||
("Adaptive Sample Limit:", "自适应采样限制:"),
|
||||
("Add Animator", "添加动画制作器"),
|
||||
|
|
@ -119,8 +120,10 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
|||
("Background Color:", "背景颜色:"),
|
||||
("Blend Mode:", "混合模式:"),
|
||||
("Blending Mode", "混合模式"),
|
||||
("Blue", "蓝"),
|
||||
("Blur", "模糊"),
|
||||
("Blur Level", "模糊级别"),
|
||||
("Boundary", "边界"),
|
||||
("Browser Storage", "浏览器存储"),
|
||||
("Browse…", "浏览…"),
|
||||
("Brush Dynamics", "画笔动态"),
|
||||
|
|
@ -229,7 +232,9 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
|||
("Frame Rate:", "帧速率:"),
|
||||
("Frame Render Time {}ms", "帧渲染时间 {} 毫秒"),
|
||||
("Frame Target:", "帧目标:"),
|
||||
("Freeze", "冻结"),
|
||||
("Grab bag", "列表"),
|
||||
("Green", "绿"),
|
||||
("Grid", "网格"),
|
||||
("Guide Layers: {}", "参考图层:{}"),
|
||||
("Guides", "参考线"),
|
||||
|
|
@ -335,6 +340,7 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
|||
("Original Duration:", "原始持续时间:"),
|
||||
("Output Cycle: {}", "输出循环:{}"),
|
||||
("Output To:", "输出到:"),
|
||||
("Overlay", "叠加"),
|
||||
("Parameter Name:", "参数名称:"),
|
||||
("Parent pick whip: drag onto a layer", "父级拾取器:拖到图层上"),
|
||||
("Pixel Aspect Ratio:", "像素长宽比:"),
|
||||
|
|
@ -359,10 +365,12 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
|||
("Protected Region", "受保护区域"),
|
||||
("Proxy Use: {}", "代理使用:{}"),
|
||||
("Push All to Comp", "全部推送到合成"),
|
||||
("RGB", "RGB"),
|
||||
("Radius", "半径"),
|
||||
("Rate Control: {}", "比特率控制:{}"),
|
||||
("Recent", "最近使用"),
|
||||
("Recording", "录制中"),
|
||||
("Red", "红"),
|
||||
("Remove", "移除"),
|
||||
("Rename", "重命名"),
|
||||
("Render: {} ms • UI {} fps{}", "渲染:{} 毫秒 • 界面 {} fps{}"),
|
||||
|
|
@ -432,6 +440,7 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
|||
("Start Timecode:", "开始时间码:"),
|
||||
("Start: {} Duration: {}", "开始:{} 持续时间:{}"),
|
||||
("Step {} of {}: {}", "第 {} 步,共 {} 步:{}"),
|
||||
("Stop", "停止"),
|
||||
("Stop {} at {}°", "停止点 {} 位于 {}°"),
|
||||
("Stored in: {}", "存储位置:{}"),
|
||||
("Stretch", "伸展"),
|
||||
|
|
@ -465,6 +474,7 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
|||
("Type a command or effect…", "输入命令或效果…"),
|
||||
("URL:", "URL:"),
|
||||
("Undock Panel", "取消停靠面板"),
|
||||
("Unfreeze", "解冻"),
|
||||
("Unlink {}", "取消链接 {}"),
|
||||
(
|
||||
"Use this option to place the currently selected layers together into a new intermediate composition.",
|
||||
|
|
@ -564,6 +574,7 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
|||
("About EffectCraft", "關於 EffectCraft"),
|
||||
("About...", "關於..."),
|
||||
("Active Camera", "活動攝影機"),
|
||||
("Alpha", "Alpha"),
|
||||
("Adapt Feature On Every Frame", "每個影格都適應特徵"),
|
||||
("Adaptive Sample Limit:", "自適應取樣限制:"),
|
||||
("Add Animator", "添加動畫制作器"),
|
||||
|
|
@ -594,8 +605,10 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
|||
("Background Color:", "背景顏色:"),
|
||||
("Blend Mode:", "混合模式:"),
|
||||
("Blending Mode", "混合模式"),
|
||||
("Blue", "藍"),
|
||||
("Blur", "模糊"),
|
||||
("Blur Level", "模糊級別"),
|
||||
("Boundary", "邊界"),
|
||||
("Browser Storage", "瀏覽器儲存"),
|
||||
("Browse…", "瀏覽…"),
|
||||
("Brush Dynamics", "筆刷動態"),
|
||||
|
|
@ -704,7 +717,9 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
|||
("Frame Rate:", "影格速率:"),
|
||||
("Frame Render Time {}ms", "影格算圖時間 {} 毫秒"),
|
||||
("Frame Target:", "幀目標:"),
|
||||
("Freeze", "凍結"),
|
||||
("Grab bag", "清單"),
|
||||
("Green", "綠"),
|
||||
("Grid", "格點"),
|
||||
("Guide Layers: {}", "參考圖層:{}"),
|
||||
("Guides", "參考線"),
|
||||
|
|
@ -810,6 +825,7 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
|||
("Original Duration:", "原始持續時間:"),
|
||||
("Output Cycle: {}", "輸出循環:{}"),
|
||||
("Output To:", "輸出到:"),
|
||||
("Overlay", "疊加"),
|
||||
("Parameter Name:", "參數名稱:"),
|
||||
("Parent pick whip: drag onto a layer", "上層拾取線:拖到圖層上"),
|
||||
("Pixel Aspect Ratio:", "像素長寬比例:"),
|
||||
|
|
@ -834,10 +850,12 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
|||
("Protected Region", "受保護區域"),
|
||||
("Proxy Use: {}", "代理使用:{}"),
|
||||
("Push All to Comp", "全部推送到合成"),
|
||||
("RGB", "RGB"),
|
||||
("Radius", "半徑"),
|
||||
("Rate Control: {}", "位元速率控制:{}"),
|
||||
("Recent", "最近使用"),
|
||||
("Recording", "錄製中"),
|
||||
("Red", "紅"),
|
||||
("Remove", "移除"),
|
||||
("Rename", "重命名"),
|
||||
("Render: {} ms • UI {} fps{}", "算圖:{} 毫秒 • 介面 {} fps{}"),
|
||||
|
|
@ -907,6 +925,7 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
|||
("Start Timecode:", "開始時間碼:"),
|
||||
("Start: {} Duration: {}", "開始:{} 持續時間:{}"),
|
||||
("Step {} of {}: {}", "第 {} 步,共 {} 步:{}"),
|
||||
("Stop", "停止"),
|
||||
("Stop {} at {}°", "停止點 {} 位於 {}°"),
|
||||
("Stored in: {}", "儲存位置:{}"),
|
||||
("Stretch", "伸展"),
|
||||
|
|
@ -940,6 +959,7 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
|||
("Type a command or effect…", "輸入命令或效果…"),
|
||||
("URL:", "URL:"),
|
||||
("Undock Panel", "取消停靠面板"),
|
||||
("Unfreeze", "解凍"),
|
||||
("Unlink {}", "取消鏈接 {}"),
|
||||
(
|
||||
"Use this option to place the currently selected layers together into a new intermediate composition.",
|
||||
|
|
@ -1063,6 +1083,7 @@ mod tests {
|
|||
("panels/precomp.rs", include_str!("../panels/precomp.rs")),
|
||||
("panels/project.rs", include_str!("../panels/project.rs")),
|
||||
("panels/properties.rs", include_str!("../panels/properties.rs")),
|
||||
("panels/roto_tool.rs", include_str!("../panels/roto_tool.rs")),
|
||||
("panels/render_queue.rs", include_str!("../panels/render_queue.rs")),
|
||||
("panels/rq_templates.rs", include_str!("../panels/rq_templates.rs")),
|
||||
("panels/scopes_panel.rs", include_str!("../panels/scopes_panel.rs")),
|
||||
|
|
|
|||
|
|
@ -777,7 +777,7 @@ fn curves_editor(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painter,
|
|||
.min(4);
|
||||
let x0 = r.min.x + 30.0;
|
||||
let cy = r.min.y + 17.0;
|
||||
let names: Vec<&str> = fw::CURVE_CHANNELS.iter().map(|c| c.1).collect();
|
||||
let names: [&str; 5] = [crate::i18n::tr("RGB"), crate::i18n::tr("Red"), crate::i18n::tr("Green"), crate::i18n::tr("Blue"), crate::i18n::tr("Alpha")];
|
||||
if let Some(n) = channel_popup(app, ui, p, x0, cy, ch, &names, egui::Id::new(("ec-cch", euid)), &format!("effectControls.effect.{euid}.curves.channel")) {
|
||||
match chan_prop {
|
||||
Some(pr) => actions.push(("prop.set".into(), json!({"layer": layer.id.0, "prop": pr.uid, "value": n}))),
|
||||
|
|
@ -866,7 +866,7 @@ fn levels_editor(
|
|||
g.get("channel").map(|pr| ectx.value(layer, pr).as_enum() as usize).unwrap_or(0).min(4)
|
||||
};
|
||||
if effect == "ec.color.levelsic" {
|
||||
let names: Vec<&str> = fw::LEVELS_CHANNELS.iter().map(|c| c.1).collect();
|
||||
let names: [&str; 5] = [crate::i18n::tr("RGB"), crate::i18n::tr("Red"), crate::i18n::tr("Green"), crate::i18n::tr("Blue"), crate::i18n::tr("Alpha")];
|
||||
if let Some(n) = channel_popup(app, ui, p, x0, cy, ch, &names, egui::Id::new(("ec-lch", euid)), &format!("effectControls.effect.{euid}.levels.channel"))
|
||||
{
|
||||
app.ui.fx_levels_channel.insert(euid, n);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use effectcraft_engine::render::{EvalCtx, RenderOpts, Renderer};
|
|||
use egui::{Align2, Color32, Pos2, Rect, Sense, Stroke, StrokeKind, pos2, vec2};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::i18n::tr;
|
||||
use crate::theme::Tokens;
|
||||
use crate::{EffectcraftApp, widgets};
|
||||
|
||||
|
|
@ -292,7 +293,7 @@ pub fn bar_buttons(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painte
|
|||
let t = app.tokens;
|
||||
let mut x = x;
|
||||
let view = app.session.state.roto.view.clone();
|
||||
for (id, label) in [("alpha", "Alpha"), ("alphaBoundary", "Boundary"), ("alphaOverlay", "Overlay")] {
|
||||
for (id, label) in [("alpha", tr("Alpha")), ("alphaBoundary", tr("Boundary")), ("alphaOverlay", tr("Overlay"))] {
|
||||
let r = Rect::from_min_size(pos2(x, bar.center().y - 10.0), vec2(66.0, 20.0));
|
||||
let on = view == id;
|
||||
if widgets::text_button(ui, r, label, on, &t, egui::Id::new(("roto-view", id))).clicked() {
|
||||
|
|
@ -309,7 +310,7 @@ pub fn bar_buttons(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painte
|
|||
let running = app.session.is_roto_running();
|
||||
x += 8.0;
|
||||
let r = Rect::from_min_size(pos2(x, bar.center().y - 10.0), vec2(74.0, 20.0));
|
||||
let label = if frozen { "Unfreeze" } else { "Freeze" };
|
||||
let label = if frozen { tr("Unfreeze") } else { tr("Freeze") };
|
||||
if widgets::text_button(ui, r, label, frozen, &t, egui::Id::new(("roto-freeze", uid))).clicked() {
|
||||
let id = if frozen { "roto.unfreeze" } else { "roto.freeze" };
|
||||
if let Err(e) = app.session.execute(id, json!({"layer": layer.id.0, "effect": uid})) {
|
||||
|
|
@ -320,7 +321,7 @@ pub fn bar_buttons(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painte
|
|||
x += 80.0;
|
||||
if running {
|
||||
let r = Rect::from_min_size(pos2(x, bar.center().y - 10.0), vec2(60.0, 20.0));
|
||||
if widgets::text_button(ui, r, "Stop", false, &t, egui::Id::new("roto-stop")).clicked() {
|
||||
if widgets::text_button(ui, r, tr("Stop"), false, &t, egui::Id::new("roto-stop")).clicked() {
|
||||
let _ = app.session.execute("roto.cancel", json!({}));
|
||||
}
|
||||
app.auto.add("layerPanel.roto.stop", r, "Stop");
|
||||
|
|
|
|||
Loading…
Reference in New Issue