mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-27 03:28:22 -06:00
i18n: Simplified Chinese (zh-hans) UI translation
- The i18n module now selects a catalog by language code instead of testing for Japanese: `language(app)` returns the code, `lookup` is shared by every catalog, and the undo/redo and workspace / 3D-view titles are formatted per language. - New SIMPLIFIED_CHINESE catalog: the same (command, English label) keys as JAPANESE, one entry per fixed menu row of the engine tree (618 rows). - `general.language` gains 简体中文 (`zh-hans`). Match System maps a Simplified Chinese locale (zh, zh-CN, zh_CN.UTF-8, zh-Hans-CN, zh-SG) to it and a Traditional one (zh-TW, zh-HK, zh-Hant) to English, which has no catalog of its own yet. - The macOS Services menu item is 服务 in Chinese. - Tests: both catalogs must cover the same fixed TREE entries; `...`, brackets and spacing keep the English shape; label/undo/panel-title/submenu/native-menu behaviour in zh-hans with file and layer names kept verbatim; the locale mapping; the preference round-trips through prefs.json.
This commit is contained in:
@@ -23,7 +23,7 @@ pub const PREFS_VERSION: u32 = 2;
|
||||
pub const PREFS_FILE: &str = "prefs.json";
|
||||
|
||||
/// Settings ▸ General ▸ Language: (label, `general.language` value).
|
||||
pub const LANGUAGES: &[(&str, &str)] = &[("Match System", "system"), ("English", "en"), ("日本語", "ja")];
|
||||
pub const LANGUAGES: &[(&str, &str)] = &[("Match System", "system"), ("English", "en"), ("日本語", "ja"), ("简体中文", "zh-hans")];
|
||||
|
||||
/// Settings ▸ Startup & Repair ▸ Window Graphics: (label, `startup.windowGraphics` value).
|
||||
pub const WINDOW_GRAPHICS: &[(&str, &str)] = &[("Automatic", "auto"), ("OpenGL (compatibility)", "gl")];
|
||||
|
||||
@@ -514,6 +514,12 @@ fn interface_language_is_validated_persisted_and_backward_compatible() {
|
||||
assert_eq!(s.prefs.general.language, "ja");
|
||||
assert_eq!(store.read(PREFS_FILE).unwrap(), saved);
|
||||
}
|
||||
// zh-hans is registered alongside en and ja: it is accepted, persisted and read back.
|
||||
s.execute("prefs.set", json!({"key": "general.language", "value": "zh-hans"})).unwrap();
|
||||
let mut zh = Session { config: Some(store.clone()), ..Default::default() };
|
||||
zh.load_settings();
|
||||
assert_eq!(zh.prefs.general.language, "zh-hans");
|
||||
s.execute("prefs.set", json!({"key": "general.language", "value": "ja"})).unwrap();
|
||||
let mut reloaded = Session { config: Some(store), ..Default::default() };
|
||||
reloaded.load_settings();
|
||||
assert_eq!(reloaded.prefs.general.language, "ja");
|
||||
|
||||
+790
-41
@@ -1,18 +1,38 @@
|
||||
//! Japanese menu labels for EffectCraft's own engine tree. Commands remain locale-independent.
|
||||
//! A command plus its source label distinguishes parameterised entries (e.g. blend modes).
|
||||
//! Empty command keys identify submenus. Dynamic filenames, user names and effect plug-in names
|
||||
//! remain verbatim; this catalog only translates the fixed menu tree.
|
||||
//! Menu labels for EffectCraft's own engine tree in each translated language. Commands remain
|
||||
//! locale-independent. A command plus its source label distinguishes parameterised entries (e.g.
|
||||
//! blend modes). Empty command keys identify submenus. Dynamic filenames, user names and effect
|
||||
//! plug-in names remain verbatim; these catalogs only translate the fixed menu tree.
|
||||
|
||||
use crate::EffectcraftApp;
|
||||
use effectcraft_engine::menus::MenuEntry;
|
||||
|
||||
pub(crate) fn japanese(app: &EffectcraftApp) -> bool {
|
||||
/// Every language with a catalog, in the order Settings ▸ General ▸ Language lists them.
|
||||
const CATALOG_CODES: [&str; 2] = ["ja", "zh-hans"];
|
||||
|
||||
/// The active interface language: the stored preference when it names a catalog, otherwise `en`
|
||||
/// (English is the source of every label and needs no lookup).
|
||||
pub(crate) fn language(app: &EffectcraftApp) -> &'static str {
|
||||
match app.session.prefs.general.language.as_str() {
|
||||
"system" => system_language() == "ja",
|
||||
l => l == "ja",
|
||||
"system" => system_language(),
|
||||
stored => code(stored),
|
||||
}
|
||||
}
|
||||
|
||||
/// `stored` as the language to show: a catalog's code, otherwise `en`.
|
||||
fn code(stored: &str) -> &'static str {
|
||||
CATALOG_CODES.iter().copied().find(|c| *c == stored).unwrap_or("en")
|
||||
}
|
||||
|
||||
/// The UI is in Japanese: the fast path for the menu builders.
|
||||
pub(crate) fn japanese(app: &EffectcraftApp) -> bool {
|
||||
language(app) == "ja"
|
||||
}
|
||||
|
||||
/// The UI is in Simplified Chinese.
|
||||
pub(crate) fn chinese(app: &EffectcraftApp) -> bool {
|
||||
language(app) == "zh-hans"
|
||||
}
|
||||
|
||||
/// Settings ▸ General ▸ Language ▸ Match System: the operating system's interface language
|
||||
/// where EffectCraft has it, else English (#229), as After Effects installs in the system's
|
||||
/// language. The browser build stays in English: it has no Japanese font of its own.
|
||||
@@ -27,25 +47,48 @@ fn system_language() -> &'static str {
|
||||
supported(None)
|
||||
}
|
||||
|
||||
/// The language EffectCraft shows for a BCP 47 locale (`ja-JP` → `ja`).
|
||||
/// The language EffectCraft shows for a BCP 47 locale (`ja-JP` → `ja`, `zh-Hans-CN` → `zh-hans`).
|
||||
/// A Chinese locale whose script or region is Traditional has no catalog of its own: English.
|
||||
fn supported(locale: Option<&str>) -> &'static str {
|
||||
match locale.and_then(|l| l.split(['-', '_']).next()) {
|
||||
Some(l) if l.eq_ignore_ascii_case("ja") => "ja",
|
||||
let Some(locale) = locale else { return "en" };
|
||||
let mut parts = locale.split(['-', '_']);
|
||||
let primary = parts.next().unwrap_or_default().to_ascii_lowercase();
|
||||
let rest: Vec<String> = parts.map(|p| p.to_ascii_lowercase()).collect();
|
||||
match primary.as_str() {
|
||||
"ja" => "ja",
|
||||
"zh" => {
|
||||
let traditional = rest.iter().any(|p| p.starts_with("hant") || p.starts_with("tw") || p.starts_with("hk") || p.starts_with("mo"));
|
||||
if traditional { "en" } else { "zh-hans" }
|
||||
}
|
||||
_ => "en",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn label<'a>(app: &EffectcraftApp, command: &str, source: &'a str) -> &'a str {
|
||||
if japanese(app) { JAPANESE.iter().find(|(id, en, _)| *id == command && *en == source).map(|(_, _, ja)| *ja).unwrap_or(source) } else { source }
|
||||
match language(app) {
|
||||
"ja" => lookup(JAPANESE, command, source),
|
||||
"zh-hans" => lookup(SIMPLIFIED_CHINESE, command, source),
|
||||
_ => source,
|
||||
}
|
||||
}
|
||||
|
||||
/// `source` looked up in `catalog` by (command, English label); the source itself when the pair is
|
||||
/// absent, so computed labels and user names stay verbatim.
|
||||
fn lookup<'a>(catalog: &[(&str, &str, &'a str)], command: &str, source: &'a str) -> &'a str {
|
||||
catalog.iter().find(|(id, en, _)| *id == command && *en == source).map(|(_, _, translated)| *translated).unwrap_or(source)
|
||||
}
|
||||
|
||||
pub(crate) fn entry(app: &EffectcraftApp, e: &MenuEntry, shown: String) -> String {
|
||||
if !japanese(app) {
|
||||
return shown;
|
||||
}
|
||||
// Undo/redo names come from the history, so they are formatted per language here rather than
|
||||
// looked up in a catalog. An English (or untranslated) interface keeps the shown label.
|
||||
let (undo, no_undo, redo, no_redo) = match language(app) {
|
||||
"ja" => ("取り消し", "取り消しできません", "やり直し", "やり直しできません"),
|
||||
"zh-hans" => ("撤销", "无可撤销的操作", "重做", "无可重做的操作"),
|
||||
_ => return shown,
|
||||
};
|
||||
match e.command.as_str() {
|
||||
"edit.undo" => app.session.history.undo.last().map(|u| format!("取り消し {}", u.0)).unwrap_or_else(|| "取り消しできません".into()),
|
||||
"edit.redo" => app.session.history.redo.last().map(|u| format!("やり直し {}", u.0)).unwrap_or_else(|| "やり直しできません".into()),
|
||||
"edit.undo" => app.session.history.undo.last().map(|u| format!("{undo} {}", u.0)).unwrap_or_else(|| no_undo.into()),
|
||||
"edit.redo" => app.session.history.redo.last().map(|u| format!("{redo} {}", u.0)).unwrap_or_else(|| no_redo.into()),
|
||||
"window.panel" => {
|
||||
let prefix = format!("{}: ", e.label);
|
||||
if let Some(name) = shown.strip_prefix(&prefix) {
|
||||
@@ -62,20 +105,657 @@ pub(crate) fn entry(app: &EffectcraftApp, e: &MenuEntry, shown: String) -> Strin
|
||||
}
|
||||
|
||||
pub(crate) fn submenu(app: &EffectcraftApp, source: &str, shown: String) -> String {
|
||||
if japanese(app) {
|
||||
if source == "Assign Shortcut to Workspace" {
|
||||
if let Some(name) = shown.strip_prefix("Assign Shortcut to “").and_then(|s| s.strip_suffix("” Workspace")) {
|
||||
return format!("ワークスペース「{name}」にショートカットを割り当て");
|
||||
match language(app) {
|
||||
"ja" => {
|
||||
if source == "Assign Shortcut to Workspace" {
|
||||
if let Some(name) = shown.strip_prefix("Assign Shortcut to “").and_then(|s| s.strip_suffix("” Workspace")) {
|
||||
return format!("ワークスペース「{name}」にショートカットを割り当て");
|
||||
}
|
||||
} else if source == "Assign Shortcut to 3D View"
|
||||
&& let Some(name) = shown.strip_prefix("Assign Shortcut to “").and_then(|s| s.strip_suffix('”'))
|
||||
{
|
||||
return format!("「{name}」にショートカットを割り当て");
|
||||
}
|
||||
} else if source == "Assign Shortcut to 3D View"
|
||||
&& let Some(name) = shown.strip_prefix("Assign Shortcut to “").and_then(|s| s.strip_suffix('”'))
|
||||
{
|
||||
return format!("「{name}」にショートカットを割り当て");
|
||||
}
|
||||
"zh-hans" => {
|
||||
if source == "Assign Shortcut to Workspace" {
|
||||
if let Some(name) = shown.strip_prefix("Assign Shortcut to “").and_then(|s| s.strip_suffix("” Workspace")) {
|
||||
return format!("为工作区“{name}”指定快捷键");
|
||||
}
|
||||
} else if source == "Assign Shortcut to 3D View"
|
||||
&& let Some(name) = shown.strip_prefix("Assign Shortcut to “").and_then(|s| s.strip_suffix('”'))
|
||||
{
|
||||
return format!("为 3D 视图“{name}”指定快捷键");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
label(app, "", &shown).into()
|
||||
}
|
||||
|
||||
/// Simplified Chinese (zh-hans): the same (command, English label) keys as `JAPANESE`, one
|
||||
/// entry per fixed menu row of the engine's menu tree.
|
||||
const SIMPLIFIED_CHINESE: &[(&str, &str, &str)] = &[
|
||||
("", "EffectCraft", "EffectCraft"),
|
||||
("app.about", "About EffectCraft...", "关于 EffectCraft..."),
|
||||
("", "Settings...", "设置..."),
|
||||
("app.settings", "General...", "常规..."),
|
||||
("app.settings", "Startup & Repair...", "启动和修复..."),
|
||||
("app.settings", "Project...", "项目..."),
|
||||
("app.settings", "Composition...", "合成..."),
|
||||
("app.settings", "Previews...", "预览..."),
|
||||
("app.settings", "Appearance...", "外观..."),
|
||||
("app.settings", "Grids & Guides...", "网格和参考线..."),
|
||||
("app.settings", "Labels...", "标签..."),
|
||||
("app.settings", "Type...", "文字..."),
|
||||
("app.settings", "Import...", "导入..."),
|
||||
("app.settings", "Export...", "导出..."),
|
||||
("app.settings", "Audio...", "音频..."),
|
||||
("app.settings", "Disk...", "磁盘..."),
|
||||
("app.settings", "Memory & CPU...", "内存和 CPU..."),
|
||||
("app.settings", "Video...", "视频..."),
|
||||
("app.settings", "3D...", "3D..."),
|
||||
("app.settings", "Scripting & Expressions...", "脚本和表达式..."),
|
||||
("app.hide", "Hide EffectCraft", "隐藏 EffectCraft"),
|
||||
("app.hideOthers", "Hide Others", "隐藏其他"),
|
||||
("app.showAll", "Show All", "全部显示"),
|
||||
("app.quit", "Quit EffectCraft", "退出 EffectCraft"),
|
||||
("", "File", "文件"),
|
||||
("", "New", "新建"),
|
||||
("file.newProject", "New Project", "新建项目"),
|
||||
("file.newFromTemplate", "New Project from Template...", "从模板新建项目..."),
|
||||
("project.newFolder", "New Folder", "新建文件夹"),
|
||||
("file.open", "Open Project...", "打开项目..."),
|
||||
("", "Open Recent", "打开最近文件"),
|
||||
("file.clearRecent", "Clear Recent Projects", "清除最近使用的项目"),
|
||||
("file.close", "Close", "关闭"),
|
||||
("file.closeProject", "Close Project", "关闭项目"),
|
||||
("file.save", "Save", "保存"),
|
||||
("", "Save As", "另存为"),
|
||||
("file.saveAs", "Save As...", "另存为..."),
|
||||
("file.saveCopy", "Save a Copy...", "保存副本..."),
|
||||
("file.saveCopyAsXml", "Save a Copy As XML...", "将副本另存为 XML..."),
|
||||
("templates.saveAs", "Save as Template...", "保存为模板..."),
|
||||
("file.incrementAndSave", "Increment and Save", "增量保存"),
|
||||
("file.revert", "Revert", "恢复"),
|
||||
("", "Import", "导入"),
|
||||
("file.import", "File...", "文件..."),
|
||||
("file.importMultiple", "Multiple Files...", "多个文件..."),
|
||||
("file.importTimeline", "Adobe Premiere Pro Project...", "Adobe Premiere Pro 项目..."),
|
||||
("file.importPlaceholder", "Placeholder...", "占位符..."),
|
||||
("file.importSolid", "Solid...", "纯色..."),
|
||||
("file.importLottie", "Lottie...", "Lottie..."),
|
||||
("file.importVanishingPoint", "Vanishing Point (.vpe)...", "消失点 (.vpe)..."),
|
||||
("essential.importTemplate", "Essential Graphics Template...", "基本图形模板..."),
|
||||
("", "Import Recent Footage", "导入最近使用的素材"),
|
||||
("file.clearRecentFootage", "Clear Recent Footage", "清除最近使用的素材"),
|
||||
("", "Export", "导出"),
|
||||
("renderQueue.add", "Add to Render Queue", "添加到渲染队列"),
|
||||
("file.exportTimeline", "Adobe Premiere Pro Project...", "Adobe Premiere Pro 项目..."),
|
||||
("file.exportLottie", "Lottie JSON...", "Lottie JSON..."),
|
||||
("essential.exportTemplate", "Essential Graphics Template...", "基本图形模板..."),
|
||||
("app.find", "Find", "查找"),
|
||||
("layer.addItem", "Add Footage to Comp", "将素材添加到合成"),
|
||||
("file.newCompFromSelection", "New Comp from Selection...", "从所选内容新建合成..."),
|
||||
("", "Dependencies", "依赖项"),
|
||||
("file.collectFiles", "Collect Files...", "收集文件..."),
|
||||
("file.consolidateFootage", "Consolidate All Footage", "整合所有素材"),
|
||||
("file.removeUnusedFootage", "Remove Unused Footage", "删除未使用的素材"),
|
||||
("file.reduceProject", "Reduce Project", "精简项目"),
|
||||
("file.findMissing", "Find Missing Effects", "查找缺失的效果"),
|
||||
("file.findMissing", "Find Missing Fonts", "查找缺失的字体"),
|
||||
("file.findMissing", "Find Missing Footage", "查找缺失的素材"),
|
||||
("file.watchFolder", "Watch Folder...", "监视文件夹..."),
|
||||
("", "Scripts", "脚本"),
|
||||
("file.installScript", "Install Script File...", "安装脚本文件..."),
|
||||
("file.installScriptUIPanel", "Install ScriptUI Panel...", "安装 ScriptUI 面板..."),
|
||||
("file.runScript", "Run Script File...", "运行脚本文件..."),
|
||||
("", "Create Proxy", "创建代理"),
|
||||
("file.createProxy", "Still...", "静止图像..."),
|
||||
("file.createProxy", "Movie...", "影片..."),
|
||||
("", "Set Proxy", "设置代理"),
|
||||
("file.setProxy", "File...", "文件..."),
|
||||
("file.setProxyNone", "None", "无"),
|
||||
("", "Interpret Footage", "解释素材"),
|
||||
("file.interpretFootage", "Main...", "主文件..."),
|
||||
("file.interpretProxy", "Proxy...", "代理..."),
|
||||
("file.rememberInterpretation", "Remember Interpretation", "记住解释"),
|
||||
("file.applyInterpretation", "Apply Interpretation", "应用解释"),
|
||||
("", "Replace Footage", "替换素材"),
|
||||
("file.replaceFootage", "File...", "文件..."),
|
||||
("file.replaceWithPlaceholder", "Placeholder...", "占位符..."),
|
||||
("file.replaceWithSolid", "Solid...", "纯色..."),
|
||||
("file.replaceWithLayeredComp", "With Layered Comp", "使用分层合成"),
|
||||
("file.reloadFootage", "Reload Footage", "重新加载素材"),
|
||||
("file.revealInFinder", "Reveal in Finder", "在 Finder 中显示"),
|
||||
("file.projectSettings", "Project Settings...", "项目设置..."),
|
||||
("app.quit", "Exit", "退出"),
|
||||
("", "Edit", "编辑"),
|
||||
("edit.undo", "Undo", "撤销"),
|
||||
("edit.redo", "Redo", "重做"),
|
||||
("", "History", "历史记录"),
|
||||
("app.commandPalette", "Quick Apply...", "快速应用..."),
|
||||
("edit.cut", "Cut", "剪切"),
|
||||
("edit.copy", "Copy", "复制"),
|
||||
("edit.copyWithPropertyLinks", "Copy with Property Links", "复制属性链接"),
|
||||
("edit.copyWithRelativePropertyLinks", "Copy with Relative Property Links", "复制相对属性链接"),
|
||||
("edit.copyExpressionOnly", "Copy Expression Only", "仅复制表达式"),
|
||||
("edit.paste", "Paste", "粘贴"),
|
||||
("edit.pasteReversedKeyframes", "Paste Reversed Keyframes", "粘贴反转关键帧"),
|
||||
("edit.pasteTextMatchFormatting", "Paste Text and Match Formatting", "粘贴文本并匹配格式"),
|
||||
("edit.pasteTextFormattingOnly", "Paste Text Formatting Only", "仅粘贴文本格式"),
|
||||
("edit.clear", "Clear", "清除"),
|
||||
("edit.duplicate", "Duplicate", "重复"),
|
||||
("edit.splitLayer", "Split Layer", "拆分图层"),
|
||||
("edit.liftWorkArea", "Lift Work Area", "提升工作区域"),
|
||||
("edit.extractWorkArea", "Extract Work Area", "提取工作区域"),
|
||||
("edit.selectAll", "Select All", "全选"),
|
||||
("edit.deselectAll", "Deselect All", "取消全部选择"),
|
||||
("", "Label", "标签"),
|
||||
("edit.selectLabelGroup", "Select Label Group", "选择标签组"),
|
||||
("edit.label", "None", "无"),
|
||||
("edit.label", "Red", "红色"),
|
||||
("edit.label", "Yellow", "黄色"),
|
||||
("edit.label", "Aqua", "水色"),
|
||||
("edit.label", "Pink", "粉色"),
|
||||
("edit.label", "Lavender", "淡紫"),
|
||||
("edit.label", "Peach", "桃红"),
|
||||
("edit.label", "Sea Foam", "海沫绿"),
|
||||
("edit.label", "Blue", "蓝色"),
|
||||
("edit.label", "Green", "绿色"),
|
||||
("edit.label", "Purple", "紫色"),
|
||||
("edit.label", "Orange", "橙色"),
|
||||
("edit.label", "Brown", "棕色"),
|
||||
("edit.label", "Fuchsia", "紫红"),
|
||||
("edit.label", "Cyan", "青色"),
|
||||
("edit.label", "Sandstone", "砂岩"),
|
||||
("edit.label", "Dark Green", "深绿"),
|
||||
("app.settings", "Edit Label Colors...", "编辑标签颜色..."),
|
||||
("", "Select Keyframe Label Group", "选择关键帧标签组"),
|
||||
("keys.selectLabelGroup", "On Selected Layers", "所选图层上"),
|
||||
("keys.selectLabelGroup", "On All Layers", "所有图层上"),
|
||||
("keys.selectLabelGroup", "Visible Keyframes on Selected Layers", "所选图层上的可见关键帧"),
|
||||
("keys.selectLabelGroup", "Visible Keyframes on All Layers", "所有图层上的可见关键帧"),
|
||||
("", "Purge", "清理"),
|
||||
("edit.purge", "All Cache...", "所有缓存..."),
|
||||
("edit.purge", "All Memory & Disk Cache...", "所有内存和磁盘缓存..."),
|
||||
("edit.purge", "All Memory", "所有内存"),
|
||||
("edit.purge", "All Disk Cache...", "所有磁盘缓存..."),
|
||||
("edit.purge", "All 3D Cache...", "所有 3D 缓存..."),
|
||||
("edit.purgeUndo", "Undo", "撤销"),
|
||||
("edit.purge", "Image Cache Memory", "图像缓存内存"),
|
||||
("edit.purge", "Snapshot", "快照"),
|
||||
("edit.editOriginal", "Edit Original...", "编辑原稿..."),
|
||||
("", "Templates", "模板"),
|
||||
("app.templates", "Render Settings...", "渲染设置..."),
|
||||
("app.templates", "Output Module...", "输出模块..."),
|
||||
("app.keyboardShortcuts", "Keyboard Shortcuts", "键盘快捷键"),
|
||||
("", "Preferences", "首选项"),
|
||||
("", "Composition", "合成"),
|
||||
("comp.new", "New Composition...", "新建合成..."),
|
||||
("comp.settings", "Composition Settings...", "合成设置..."),
|
||||
("comp.setPosterTime", "Set Poster Time", "设置海报时间"),
|
||||
("comp.trimToWorkArea", "Trim Comp to Work Area", "将合成修剪到工作区域"),
|
||||
("comp.cropToRegionOfInterest", "Crop Comp to Region of Interest", "将合成裁剪到目标区域"),
|
||||
("comp.cropToLayerBounds", "Crop Comp to Selected Layer(s) Bounds", "将合成裁剪到所选图层(单个或多个)的边界"),
|
||||
("render.addOutputModule", "Add Output Module", "添加输出模块"),
|
||||
("", "Preview", "预览"),
|
||||
("playback.toggle", "Play Current Preview", "播放当前预览"),
|
||||
("playback.cacheWhenIdle", "Cache Frames When Idle", "空闲时缓存帧"),
|
||||
("playback.audio", "Audio", "音频"),
|
||||
("", "Save Frame As", "将帧另存为"),
|
||||
("comp.saveFrameAs", "File...", "文件..."),
|
||||
("comp.saveFrameAsPsd", "Photoshop Layers...", "Photoshop 图层..."),
|
||||
("comp.saveFrameAsExr", "ProEXR...", "ProEXR..."),
|
||||
("render.preRender", "Pre-render...", "预渲染..."),
|
||||
("render.saveCurrentPreview", "Save Current Preview...", "保存当前预览..."),
|
||||
("comp.openInEssentialGraphics", "Open in Essential Graphics", "在基本图形中打开"),
|
||||
("", "Responsive Design — Time", "响应式设计 — 时间"),
|
||||
("comp.responsiveTime", "Create Intro", "创建片头"),
|
||||
("comp.responsiveTime", "Create Outro", "创建片尾"),
|
||||
("comp.responsiveTime", "Create Protected Region from Work Area", "从工作区域创建受保护区域"),
|
||||
("comp.flowchart", "Composition Flowchart", "合成流程图"),
|
||||
("comp.miniFlowchart", "Composition Mini-Flowchart", "合成迷你流程图"),
|
||||
("", "VR", "VR"),
|
||||
("comp.vr.createEnvironment", "Create VR Environment...", "创建 VR 环境..."),
|
||||
("comp.vr.extractCubemap", "Extract Cubemap...", "提取立方体贴图..."),
|
||||
("", "Layer", "图层"),
|
||||
("layer.newText", "Text", "文本"),
|
||||
("layer.newSolid", "Solid...", "纯色..."),
|
||||
("layer.newLight", "Light...", "灯光..."),
|
||||
("layer.newCamera", "Camera...", "摄像机..."),
|
||||
("layer.newNull", "Null Object", "空对象"),
|
||||
("layer.newShape", "Shape Layer", "形状图层"),
|
||||
("layer.newAdjustment", "Adjustment Layer", "调整图层"),
|
||||
("layer.newContentAwareFill", "Content-Aware Fill Layer...", "内容识别填充图层..."),
|
||||
("layer.new3dPrimitive", "Cube", "立方体"),
|
||||
("layer.new3dPrimitive", "Sphere", "球体"),
|
||||
("layer.new3dPrimitive", "Plane", "平面"),
|
||||
("layer.new3dPrimitive", "Torus", "圆环"),
|
||||
("layer.new3dPrimitive", "Cone", "圆锥"),
|
||||
("layer.new3dPrimitive", "Cylinder", "圆柱"),
|
||||
("layer.settings", "Layer Settings...", "图层设置..."),
|
||||
("layer.openLayer", "Open Layer", "打开图层"),
|
||||
("layer.openSource", "Open Layer Source", "打开图层源"),
|
||||
("layer.revealInFinder", "Reveal in Finder", "在 Finder 中显示"),
|
||||
("", "Mask", "蒙版"),
|
||||
("layer.addMask", "New Mask", "新建蒙版"),
|
||||
("layer.mask.shape", "Mask Shape...", "蒙版形状..."),
|
||||
("layer.mask.set", "Mask Feather...", "蒙版羽化..."),
|
||||
("layer.mask.set", "Mask Opacity...", "蒙版不透明度..."),
|
||||
("layer.mask.set", "Mask Expansion...", "蒙版扩展..."),
|
||||
("layer.mask.reset", "Reset Mask", "重置蒙版"),
|
||||
("layer.mask.remove", "Remove Mask", "移除蒙版"),
|
||||
("layer.mask.removeAll", "Remove All Masks", "移除所有蒙版"),
|
||||
("track.mask", "Track Mask", "跟踪蒙版"),
|
||||
("", "Mode", "模式"),
|
||||
("layer.mask.mode", "None", "无"),
|
||||
("layer.mask.mode", "Add", "添加"),
|
||||
("layer.mask.mode", "Subtract", "减去"),
|
||||
("layer.mask.mode", "Intersect", "相交"),
|
||||
("layer.mask.mode", "Lighten", "变亮"),
|
||||
("layer.mask.mode", "Darken", "变暗"),
|
||||
("layer.mask.mode", "Difference", "差值"),
|
||||
("layer.mask.invert", "Inverted", "反转"),
|
||||
("layer.mask.lock", "Locked", "已锁定"),
|
||||
("", "Motion Blur", "运动模糊"),
|
||||
("layer.mask.motionBlur", "Same As Layer", "同图层"),
|
||||
("layer.mask.motionBlur", "On", "开"),
|
||||
("layer.mask.motionBlur", "Off", "关闭"),
|
||||
("", "Feather Falloff", "羽化衰减"),
|
||||
("layer.mask.featherFalloff", "Smooth", "平滑"),
|
||||
("layer.mask.featherFalloff", "Linear", "线性"),
|
||||
("layer.mask.unlockAll", "Unlock All Masks", "解锁所有蒙版"),
|
||||
("layer.mask.lockOthers", "Lock Other Masks", "锁定其他蒙版"),
|
||||
("layer.mask.hideLocked", "Hide Locked Masks", "隐藏锁定的蒙版"),
|
||||
("", "Mask and Shape Path", "蒙版和形状路径"),
|
||||
("path.rotoBezier", "RotoBezier", "RotoBezier"),
|
||||
("mask.setClosed", "Closed", "封闭"),
|
||||
("path.convertToBezier", "Convert To Bezier Path", "转换为贝塞尔路径"),
|
||||
("path.setFirstVertex", "Set First Vertex", "设置第一个顶点"),
|
||||
("path.freeTransform", "Free Transform Points", "自由变换点"),
|
||||
("", "Quality", "品质"),
|
||||
("layer.quality", "Best", "最佳"),
|
||||
("layer.quality", "Draft", "草图"),
|
||||
("layer.quality", "Wireframe", "线框"),
|
||||
("layer.sampling", "Bilinear", "双线性"),
|
||||
("layer.sampling", "Bicubic", "双三次"),
|
||||
("", "Switches", "开关"),
|
||||
("layer.hideOtherVideo", "Hide Other Video", "隐藏其他视频"),
|
||||
("layer.showAllVideo", "Show All Video", "显示所有视频"),
|
||||
("layer.unlockAll", "Unlock All Layers", "解锁所有图层"),
|
||||
("layer.expressions", "Enable Expressions", "启用表达式"),
|
||||
("layer.expressions", "Disable Expressions", "禁用表达式"),
|
||||
("layer.setSwitch", "Shy", "隐藏"),
|
||||
("layer.setSwitch", "Lock", "锁定"),
|
||||
("layer.setSwitch", "Audio", "音频"),
|
||||
("layer.setSwitch", "Video", "视频"),
|
||||
("layer.setSwitch", "Solo", "独奏"),
|
||||
("layer.setSwitch", "Effect", "效果"),
|
||||
("layer.setSwitch", "Collapse", "折叠"),
|
||||
("layer.setSwitch", "Motion Blur", "运动模糊"),
|
||||
("layer.setSwitch", "Adjustment Layer", "调整图层"),
|
||||
("", "Transform", "变换"),
|
||||
("layer.transform", "Reset", "重置"),
|
||||
("layer.setTransform", "Anchor Point...", "锚点..."),
|
||||
("layer.setTransform", "Position...", "位置..."),
|
||||
("layer.setTransform", "Scale...", "缩放..."),
|
||||
("layer.setTransform", "Orientation...", "方向..."),
|
||||
("layer.setTransform", "Rotation...", "旋转..."),
|
||||
("layer.setTransform", "Opacity...", "不透明度..."),
|
||||
("layer.transform", "Flip Horizontal", "水平翻转"),
|
||||
("layer.transform", "Flip Vertical", "垂直翻转"),
|
||||
("layer.transform", "Center In View", "在视图中居中"),
|
||||
("layer.centerAnchor", "Center Anchor Point in Layer Content", "将锚点居中到图层内容"),
|
||||
("layer.transform", "Fit to Comp", "适合合成"),
|
||||
("layer.transform", "Fit to Comp Width", "适合合成宽度"),
|
||||
("layer.transform", "Fit to Comp Height", "适合合成高度"),
|
||||
("layer.autoOrient", "Auto-Orient...", "自动定向..."),
|
||||
("", "Time", "时间"),
|
||||
("layer.enableTimeRemap", "Enable Time Remapping", "启用时间重映射"),
|
||||
("layer.timeReverse", "Time-Reverse Layer", "时间反向图层"),
|
||||
("layer.timeStretch", "Time Stretch...", "时间伸展..."),
|
||||
("layer.freezeFrame", "Freeze Frame", "冻结帧"),
|
||||
("layer.freezeOnLastFrame", "Freeze On Last Frame", "冻结在最后一帧"),
|
||||
("layer.alignVideoToData", "Align Video to Data", "将视频对齐到数据"),
|
||||
("", "Frame Blending", "帧混合"),
|
||||
("layer.frameBlending", "Off", "关闭"),
|
||||
("layer.frameBlending", "Frame Mix", "帧混合"),
|
||||
("layer.frameBlending", "Pixel Motion", "像素运动"),
|
||||
("layer.setSwitch", "3D Layer", "3D 图层"),
|
||||
("layer.setSwitch", "Guide Layer", "参考图层"),
|
||||
("layer.environment", "Environment Layer", "环境图层"),
|
||||
("", "Markers", "标记"),
|
||||
("layer.addMarker", "Add Marker", "添加标记"),
|
||||
("layer.updateMarkersFromSource", "Update Markers From Source", "从源更新标记"),
|
||||
("layer.markersLock", "Lock Markers", "锁定标记"),
|
||||
("layer.deleteAllMarkers", "Delete All Markers", "删除所有标记"),
|
||||
("layer.setSwitch", "Preserve Transparency", "保留透明度"),
|
||||
("", "Blending Mode", "混合模式"),
|
||||
("layer.setBlendMode", "Normal", "正常"),
|
||||
("layer.setBlendMode", "Dissolve", "溶解"),
|
||||
("layer.setBlendMode", "Dancing Dissolve", "动态溶解"),
|
||||
("layer.setBlendMode", "Darken", "变暗"),
|
||||
("layer.setBlendMode", "Multiply", "正片叠底"),
|
||||
("layer.setBlendMode", "Color Burn", "颜色加深"),
|
||||
("layer.setBlendMode", "Classic Color Burn", "经典颜色加深"),
|
||||
("layer.setBlendMode", "Linear Burn", "线性加深"),
|
||||
("layer.setBlendMode", "Darker Color", "深色"),
|
||||
("layer.setBlendMode", "Add", "添加"),
|
||||
("layer.setBlendMode", "Lighten", "变亮"),
|
||||
("layer.setBlendMode", "Screen", "滤色"),
|
||||
("layer.setBlendMode", "Color Dodge", "颜色减淡"),
|
||||
("layer.setBlendMode", "Classic Color Dodge", "经典颜色减淡"),
|
||||
("layer.setBlendMode", "Linear Dodge", "线性减淡"),
|
||||
("layer.setBlendMode", "Lighter Color", "浅色"),
|
||||
("layer.setBlendMode", "Overlay", "叠加"),
|
||||
("layer.setBlendMode", "Soft Light", "柔光"),
|
||||
("layer.setBlendMode", "Hard Light", "强光"),
|
||||
("layer.setBlendMode", "Linear Light", "线性光"),
|
||||
("layer.setBlendMode", "Vivid Light", "亮光"),
|
||||
("layer.setBlendMode", "Pin Light", "点光"),
|
||||
("layer.setBlendMode", "Hard Mix", "实色混合"),
|
||||
("layer.setBlendMode", "Difference", "差值"),
|
||||
("layer.setBlendMode", "Classic Difference", "经典差值"),
|
||||
("layer.setBlendMode", "Exclusion", "排除"),
|
||||
("layer.setBlendMode", "Subtract", "减去"),
|
||||
("layer.setBlendMode", "Divide", "划分"),
|
||||
("layer.setBlendMode", "Hue", "色相"),
|
||||
("layer.setBlendMode", "Saturation", "饱和度"),
|
||||
("layer.setBlendMode", "Color", "颜色"),
|
||||
("layer.setBlendMode", "Luminosity", "明度"),
|
||||
("layer.setBlendMode", "Stencil Alpha", "Alpha 模板"),
|
||||
("layer.setBlendMode", "Stencil Luma", "亮度模板"),
|
||||
("layer.setBlendMode", "Silhouette Alpha", "Alpha 轮廓"),
|
||||
("layer.setBlendMode", "Silhouette Luma", "亮度轮廓"),
|
||||
("layer.setBlendMode", "Alpha Add", "Alpha 添加"),
|
||||
("layer.setBlendMode", "Luminescent Premul", "发光预乘"),
|
||||
("layer.setBlendMode", "Next Blending Mode", "下一个混合模式"),
|
||||
("layer.setBlendMode", "Previous Blending Mode", "上一个混合模式"),
|
||||
("", "Track Matte", "轨道遮罩"),
|
||||
("layer.trackMatte", "No Track Matte", "无轨道遮罩"),
|
||||
("layer.trackMatte", "Alpha Matte", "Alpha 遮罩"),
|
||||
("layer.trackMatte", "Alpha Inverted Matte", "Alpha 反转遮罩"),
|
||||
("layer.trackMatte", "Luma Matte", "亮度遮罩"),
|
||||
("layer.trackMatte", "Luma Inverted Matte", "亮度反转遮罩"),
|
||||
("layer.trackMatte", "Matte with Layer Above", "使用上方图层作为遮罩"),
|
||||
("layer.trackMatte", "Matte with Layer Below", "使用下方图层作为遮罩"),
|
||||
("", "Layer Styles", "图层样式"),
|
||||
("layer.style.options", "Layer Style Options...", "图层样式选项..."),
|
||||
("layer.style.convertToEditable", "Convert to Editable Styles", "转换为可编辑样式"),
|
||||
("layer.style.showAll", "Show All", "全部显示"),
|
||||
("layer.style.removeAll", "Remove All", "全部移除"),
|
||||
("layer.style.dropShadow", "Drop Shadow", "投影"),
|
||||
("layer.style.innerShadow", "Inner Shadow", "内阴影"),
|
||||
("layer.style.outerGlow", "Outer Glow", "外发光"),
|
||||
("layer.style.innerGlow", "Inner Glow", "内发光"),
|
||||
("layer.style.bevelEmboss", "Bevel and Emboss", "斜面和浮雕"),
|
||||
("layer.style.satin", "Satin", "光泽"),
|
||||
("layer.style.colorOverlay", "Color Overlay", "颜色叠加"),
|
||||
("layer.style.gradientOverlay", "Gradient Overlay", "渐变叠加"),
|
||||
("layer.style.stroke", "Stroke", "描边"),
|
||||
("path.groupShapes", "Group Shapes", "组合形状"),
|
||||
("path.ungroupShapes", "Ungroup Shapes", "取消组合形状"),
|
||||
("", "Arrange", "排列"),
|
||||
("layer.arrange", "Bring Layer to Front", "将图层移到最前"),
|
||||
("layer.arrange", "Bring Layer Forward", "将图层前移一层"),
|
||||
("layer.arrange", "Send Layer Backward", "将图层后移一层"),
|
||||
("layer.arrange", "Send Layer to Back", "将图层移到最后"),
|
||||
("", "Reveal", "显示"),
|
||||
("layer.revealSource", "Reveal Layer Source in Project", "在项目中显示图层源"),
|
||||
("comp.flowchart", "Reveal Layer in Project Flowchart", "在项目流程图中显示图层"),
|
||||
("comp.revealInProject", "Reveal Composition in Project", "在项目中显示合成"),
|
||||
("layer.revealExpressionErrors", "Reveal Expression Errors", "显示表达式错误"),
|
||||
("", "Create", "创建"),
|
||||
("layer.create", "Convert to Editable Text", "转换为可编辑文本"),
|
||||
("layer.create", "Create Shapes from Text", "从文本创建形状"),
|
||||
("layer.create", "Create Masks from Text", "从文本创建蒙版"),
|
||||
("layer.create", "Create Shapes from Vector Layer", "从矢量图层创建形状"),
|
||||
("layer.create", "Create Keyframes from Data", "从数据创建关键帧"),
|
||||
("layer.create", "Null Controllers for Positional Points", "为位置点创建空对象控制器"),
|
||||
("layer.create", "Null Controllers for Path Points", "为路径点创建空对象控制器"),
|
||||
("layer.create", "Nulls Following Path Points", "跟随路径点的空对象"),
|
||||
("layer.create", "Null Tracing Along Path", "沿路径描边的空对象"),
|
||||
("layer.create", "Create 3D Layer Instance", "创建 3D 图层实例"),
|
||||
("", "Camera", "摄像机"),
|
||||
("camera.fromView", "Create Camera from 3D View", "从 3D 视图创建摄像机"),
|
||||
("camera.stereoRig", "Create Stereo 3D Rig", "创建立体 3D 装置"),
|
||||
("camera.orbitNull", "Create Orbit Null", "创建环绕空对象"),
|
||||
("camera.fromModel", "Create Cameras from 3D Model", "从 3D 模型创建摄像机"),
|
||||
("camera.linkFocusToPoi", "Link Focus Distance to Point of Interest", "将焦距链接到目标点"),
|
||||
("camera.linkFocusToLayer", "Link Focus Distance to Layer", "将焦距链接到图层"),
|
||||
("camera.setFocusToLayer", "Set Focus Distance to Layer", "将焦距设置为图层"),
|
||||
("layer.cameraSettings", "Camera Settings...", "摄像机设置..."),
|
||||
("view.reset3DView", "Reset 3D View", "重置 3D 视图"),
|
||||
("", "Light", "灯光"),
|
||||
("light.fromModel", "Create Lights from 3D Model", "从 3D 模型创建灯光"),
|
||||
("light.controlWithCamera", "Control Light with Camera", "用摄像机控制灯光"),
|
||||
("light.environmentBackground", "Create Environment Light Background Layer", "创建环境光背景图层"),
|
||||
("", "Material", "材质"),
|
||||
("material.revealSource", "Reveal Material Source in Project", "在项目中显示材质源"),
|
||||
("material.reset", "Reset Material", "重置材质"),
|
||||
("material.duplicateAssign", "Duplicate and Assign Material", "复制并指定材质"),
|
||||
("layer.autoTrace", "Auto-trace...", "自动追踪..."),
|
||||
("layer.precompose", "Pre-compose...", "预合成..."),
|
||||
("layer.sceneEditDetection", "Scene Edit Detection...", "场景编辑检测..."),
|
||||
("", "Effect", "效果"),
|
||||
("window.panel", "Effect Controls", "效果控件"),
|
||||
("effect.applyLast", "Last Effect", "上一个效果"),
|
||||
("effect.removeAll", "Remove All", "全部移除"),
|
||||
("effect.manage", "Manage Effects...", "管理效果..."),
|
||||
("effect.plugins.load", "Load Effect Plug-in...", "加载效果插件..."),
|
||||
("", "Animation", "动画"),
|
||||
("anim.savePreset", "Save Animation Preset...", "保存动画预设..."),
|
||||
("anim.applyPreset", "Apply Animation Preset...", "应用动画预设..."),
|
||||
("", "Recent Animation Presets", "最近的动画预设"),
|
||||
("anim.clearRecentPresets", "Clear Recent Presets", "清除最近的预设"),
|
||||
("anim.browsePresets", "Browse Presets...", "浏览预设..."),
|
||||
("", "Text Animation Presets", "文本动画预设"),
|
||||
("layer.applyTextPreset", "Typewriter", "打字机"),
|
||||
("layer.applyTextPreset", "Fade Up Characters", "字符淡入"),
|
||||
("layer.applyTextPreset", "Bounce In Words", "单词弹入"),
|
||||
("layer.applyTextPreset", "Tracking In", "字距进入"),
|
||||
("layer.applyTextPreset", "Scramble", "乱序"),
|
||||
("layer.applyTextPreset", "Blur In", "模糊进入"),
|
||||
("layer.applyTextPreset", "Jitter", "抖动"),
|
||||
("layer.applyTextPreset", "Drop In Lines", "行落下"),
|
||||
("anim.addKeyframe", "Add Keyframe", "添加关键帧"),
|
||||
("keys.toggleHold", "Toggle Hold Keyframe", "切换定格关键帧"),
|
||||
("keys.interpolation", "Keyframe Interpolation...", "关键帧插值..."),
|
||||
("keys.velocity", "Keyframe Velocity...", "关键帧速度..."),
|
||||
("", "Keyframe Assistant", "关键帧辅助"),
|
||||
("keys.audioToKeyframes", "Convert Audio to Keyframes", "将音频转换为关键帧"),
|
||||
("prop.convertExpressionToKeyframes", "Convert Expression to Keyframes", "将表达式转换为关键帧"),
|
||||
("keys.easyEase", "Easy Ease", "缓动"),
|
||||
("keys.easyEaseIn", "Easy Ease In", "缓入"),
|
||||
("keys.easyEaseOut", "Easy Ease Out", "缓出"),
|
||||
("keys.exponentialScale", "Exponential Scale", "指数缩放"),
|
||||
("keys.rpfCameraImport", "RPF Camera Import", "RPF 摄像机导入"),
|
||||
("layer.sequence", "Sequence Layers...", "序列图层..."),
|
||||
("keys.timeReverse", "Time-Reverse Keyframes", "时间反向关键帧"),
|
||||
("", "Animate Text", "动画文字"),
|
||||
("layer.enablePerChar3D", "Enable Per-character 3D", "启用逐字符 3D"),
|
||||
("layer.addTextAnimator", "Anchor Point", "锚点"),
|
||||
("layer.addTextAnimator", "Position", "位置"),
|
||||
("layer.addTextAnimator", "Scale", "缩放"),
|
||||
("layer.addTextAnimator", "Skew", "斜切"),
|
||||
("layer.addTextAnimator", "Rotation", "旋转"),
|
||||
("layer.addTextAnimator", "Opacity", "不透明度"),
|
||||
("layer.addTextAnimator", "All Transform Properties", "所有变换属性"),
|
||||
("", "Fill Color", "填充颜色"),
|
||||
("layer.addTextAnimator", "RGB", "RGB"),
|
||||
("layer.addTextAnimator", "Hue", "色相"),
|
||||
("layer.addTextAnimator", "Saturation", "饱和度"),
|
||||
("layer.addTextAnimator", "Brightness", "亮度"),
|
||||
("", "Stroke Color", "描边颜色"),
|
||||
("layer.addTextAnimator", "Stroke Width", "描边宽度"),
|
||||
("layer.addTextAnimator", "Tracking", "字符间距"),
|
||||
("layer.addTextAnimator", "Line Anchor", "行锚点"),
|
||||
("layer.addTextAnimator", "Line Spacing", "行间距"),
|
||||
("layer.addTextAnimator", "Character Offset", "字符偏移"),
|
||||
("layer.addTextAnimator", "Character Value", "字符值"),
|
||||
("layer.addTextAnimator", "Blur", "模糊"),
|
||||
("text.animatorFontAxes", "Variable Font Axes", "可变字体轴"),
|
||||
("", "Add Text Selector", "添加文本选择器"),
|
||||
("text.addSelector", "Range", "范围"),
|
||||
("text.addSelector", "Wiggly", "摆动"),
|
||||
("text.addSelector", "Expression", "表达式"),
|
||||
("text.removeAllAnimators", "Remove All Text Animators", "移除所有文本动画制作器"),
|
||||
("prop.setExpression", "Add Expression", "添加表达式"),
|
||||
("essential.addProperty", "Add Property to Essential Graphics", "将属性添加到基本图形"),
|
||||
("prop.separateDimensions", "Separate Dimensions", "分离尺寸"),
|
||||
("track.camera", "Track Camera", "跟踪摄像机"),
|
||||
("track.warpStabilizer", "Warp Stabilizer VFX", "变形稳定器 VFX"),
|
||||
("track.motion", "Track Motion", "跟踪运动"),
|
||||
("track.stabilize", "Stabilize Motion", "稳定运动"),
|
||||
("track.property", "Track this Property", "跟踪此属性"),
|
||||
("anim.reveal", "Reveal Properties with Keyframes", "显示带关键帧的属性"),
|
||||
("anim.reveal", "Reveal Properties with Animation", "显示带动画的属性"),
|
||||
("anim.reveal", "Reveal All Modified Properties", "显示所有已修改的属性"),
|
||||
("", "View", "视图"),
|
||||
("view.newViewer", "New Viewer", "新建视图"),
|
||||
("view.splitLockedViewer", "Split with New Locked Viewer", "使用新的锁定视图拆分"),
|
||||
("view.zoomIn", "Zoom In", "放大"),
|
||||
("view.zoomOut", "Zoom Out", "缩小"),
|
||||
("", "Resolution", "分辨率"),
|
||||
("view.res.full", "Full", "完整"),
|
||||
("view.res.half", "Half", "二分之一"),
|
||||
("view.res.third", "Third", "三分之一"),
|
||||
("view.res.quarter", "Quarter", "四分之一"),
|
||||
("view.res.custom", "Custom...", "自定义..."),
|
||||
("view.displayColorManagement", "Use Display Color Management", "使用显示器颜色管理"),
|
||||
("", "Simulate Output", "模拟输出"),
|
||||
("view.simulateOutput", "No Output Simulation", "无输出模拟"),
|
||||
("view.simulateOutput", "HDTV (Rec. 709)", "HDTV (Rec. 709)"),
|
||||
("view.simulateOutput", "SDTV NTSC", "SDTV NTSC"),
|
||||
("view.simulateOutput", "SDTV PAL", "SDTV PAL"),
|
||||
("view.simulateOutput", "Legacy Macintosh RGB (Gamma 1.8)", "旧版 Macintosh RGB (Gamma 1.8)"),
|
||||
("view.simulateOutput", "Internet Standard RGB (sRGB)", "互联网标准 RGB (sRGB)"),
|
||||
("view.simulateOutput", "UHDTV (Rec. 2020)", "UHDTV (Rec. 2020)"),
|
||||
("view.simulateOutput", "Display P3", "Display P3"),
|
||||
("view.simulateOutput", "Linear (1.0 Gamma)", "线性 (1.0 Gamma)"),
|
||||
("view.customRgb", "My Custom RGB...", "我的自定义 RGB..."),
|
||||
("view.simulateOutput", "Custom...", "自定义..."),
|
||||
("view.rulers", "Show Rulers", "显示标尺"),
|
||||
("", "Panel Background Color", "面板背景颜色"),
|
||||
("view.panelBackground", "Black", "黑色"),
|
||||
("view.panelBackground", "Dark Gray", "深灰色"),
|
||||
("view.panelBackground", "Medium Gray (Default)", "中灰色 (默认)"),
|
||||
("view.panelBackground", "Light Gray", "浅灰色"),
|
||||
("view.panelBackground", "White", "白色"),
|
||||
("view.panelBackground", "Custom", "自定义"),
|
||||
("view.panelBackground", "Select Custom Background Color...", "选择自定义背景颜色..."),
|
||||
("view.guides", "Show Guides", "显示参考线"),
|
||||
("view.snapToGuides", "Snap to Guides", "对齐到参考线"),
|
||||
("view.lockGuides", "Lock Guides", "锁定参考线"),
|
||||
("view.addGuide", "Add Guide...", "添加参考线..."),
|
||||
("view.clearGuides", "Clear Guides", "清除参考线"),
|
||||
("view.importGuides", "Import Guides...", "导入参考线..."),
|
||||
("view.exportGuides", "Export Guides...", "导出参考线..."),
|
||||
("view.grid", "Show Grid", "显示网格"),
|
||||
("view.snapToGrid", "Snap to Grid", "对齐到网格"),
|
||||
("view.snapping", "Snapping", "吸附"),
|
||||
("view.options", "View Options...", "视图选项..."),
|
||||
("view.layerControls", "Show Layer Controls", "显示图层控件"),
|
||||
("", "Switch View Layout", "切换视图布局"),
|
||||
("view.layout", "1 View", "1 个视图"),
|
||||
("view.layout", "2 Views", "2 个视图"),
|
||||
("view.layout", "4 Views", "4 个视图"),
|
||||
("view.shareViewOptions", "Share View Options", "共享视图选项"),
|
||||
("", "Switch 3D View", "切换 3D 视图"),
|
||||
("view.3d.activeCamera", "Active Camera", "活动摄像机"),
|
||||
("view.3d.default", "Default", "默认"),
|
||||
("view.3d.front", "Front", "正面"),
|
||||
("view.3d.left", "Left", "左侧"),
|
||||
("view.3d.top", "Top", "顶部"),
|
||||
("view.3d.back", "Back", "背面"),
|
||||
("view.3d.right", "Right", "右侧"),
|
||||
("view.3d.bottom", "Bottom", "底部"),
|
||||
("view.3d.custom1", "Custom View 1", "自定义视图 1"),
|
||||
("view.3d.custom2", "Custom View 2", "自定义视图 2"),
|
||||
("view.3d.custom3", "Custom View 3", "自定义视图 3"),
|
||||
("", "Assign Shortcut to 3D View", "为 3D 视图指定快捷键"),
|
||||
("view.3d.last", "Switch to Last 3D View", "切换到上一个 3D 视图"),
|
||||
("view.lookAtSelected", "Look at Selected Layers", "查看所选图层"),
|
||||
("view.lookAtAll", "Look at All Layers", "查看所有图层"),
|
||||
("time.set", "Go to Time...", "转到时间..."),
|
||||
("view.fullScreen", "Enter Full Screen", "进入全屏"),
|
||||
("", "Window", "窗口"),
|
||||
("", "Workspace", "工作区"),
|
||||
("window.workspace", "Default", "默认"),
|
||||
("window.workspace", "Review", "审阅"),
|
||||
("window.workspace", "Learn", "学习"),
|
||||
("window.workspace", "Small Screen", "小屏幕"),
|
||||
("window.workspace", "Standard", "标准"),
|
||||
("window.workspace", "All Panels", "所有面板"),
|
||||
("window.workspace", "Animation", "动画"),
|
||||
("window.workspace", "Color", "颜色"),
|
||||
("window.workspace", "Effects", "效果"),
|
||||
("window.workspace", "Essential Graphics", "基本图形"),
|
||||
("window.workspace", "Minimal", "最小"),
|
||||
("window.workspace", "Motion Tracking", "运动跟踪"),
|
||||
("window.workspace", "Paint", "绘画"),
|
||||
("window.workspace", "Text", "文本"),
|
||||
("window.workspace", "Undocked Panels", "浮动面板"),
|
||||
("window.resetWorkspace", "Reset to Saved Layout", "重置为已保存的布局"),
|
||||
("window.saveWorkspace", "Save Changes to this Workspace", "将更改保存到此工作区"),
|
||||
("window.saveWorkspaceAs", "Save as New Workspace...", "另存为新工作区..."),
|
||||
("window.editWorkspaces", "Edit Workspaces...", "编辑工作区..."),
|
||||
("", "Assign Shortcut to Workspace", "为工作区指定快捷键"),
|
||||
("window.panel", "Align", "对齐"),
|
||||
("window.panel", "Audio", "音频"),
|
||||
("window.panel", "Brushes", "画笔"),
|
||||
("window.panel", "Character", "字符"),
|
||||
("window.panel", "Content-Aware Fill", "内容识别填充"),
|
||||
("window.panel", "Effects & Presets", "效果和预设"),
|
||||
("window.panel", "Essential Graphics", "基本图形"),
|
||||
("window.panel", "Info", "信息"),
|
||||
("help.inAppTutorials", "Learn", "学习"),
|
||||
("window.panel", "Lumetri Scopes", "Lumetri 示波器"),
|
||||
("window.panel", "Mask Interpolation", "蒙版插值"),
|
||||
("window.panel", "Media Browser", "媒体浏览器"),
|
||||
("window.panel", "Metadata", "元数据"),
|
||||
("window.panel", "Motion Sketch", "运动草图"),
|
||||
("window.panel", "Paint", "绘画"),
|
||||
("window.panel", "Paragraph", "段落"),
|
||||
("window.panel", "Preview", "预览"),
|
||||
("window.panel", "Progress", "进度"),
|
||||
("window.panel", "Properties", "属性"),
|
||||
("window.panel", "Script Console", "脚本控制台"),
|
||||
("window.panel", "Smoother", "平滑器"),
|
||||
("window.panel", "Tools", "工具"),
|
||||
("window.panel", "Tracker", "跟踪器"),
|
||||
("window.panel", "Wiggler", "摆动器"),
|
||||
("window.panel", "Composition", "合成"),
|
||||
("window.panel", "Flowchart", "流程图"),
|
||||
("window.panel", "Footage", "素材"),
|
||||
("window.panel", "Layer", "图层"),
|
||||
("window.panel", "Project", "项目"),
|
||||
("window.panel", "Render Queue", "渲染队列"),
|
||||
("window.panel", "Timeline", "时间轴"),
|
||||
("window.panel", "Create Nulls From Paths", "从路径创建空对象"),
|
||||
("window.panel", "Ease Presets", "缓动预设"),
|
||||
("window.panel", "VR Comp Editor", "VR 合成编辑器"),
|
||||
("", "Help", "帮助"),
|
||||
("help.docs", "EffectCraft Help...", "EffectCraft 帮助..."),
|
||||
("help.docs", "Scripting Help...", "脚本帮助..."),
|
||||
("help.docs", "Expression Reference...", "表达式参考..."),
|
||||
("help.docs", "Effect Reference...", "效果参考..."),
|
||||
("anim.browsePresets", "Animation Presets...", "动画预设..."),
|
||||
("app.keyboardShortcuts", "Keyboard Shortcuts...", "键盘快捷键..."),
|
||||
("help.inAppTutorials", "In-App Tutorials...", "应用内教程..."),
|
||||
("help.onlineTutorials", "Online Tutorials...", "在线教程..."),
|
||||
("help.systemReport", "System Compatibility Report...", "系统兼容性报告..."),
|
||||
("help.enableLogging", "Enable Logging", "启用日志记录"),
|
||||
("help.revealLogFile", "Reveal Logging File", "显示日志文件"),
|
||||
("help.discord", "Join the ArtCraft Discord...", "加入 ArtCraft 的 Discord 社区..."),
|
||||
("help.reportIssue", "Provide Feedback...", "提供反馈..."),
|
||||
("help.website", "ArtCraft Website", "ArtCraft 网站"),
|
||||
("help.appPage", "EffectCraft Home Page", "EffectCraft 主页"),
|
||||
("help.github", "EffectCraft on GitHub", "GitHub 上的 EffectCraft"),
|
||||
("file.openDemoProject", "Open Demo Project", "打开示例项目"),
|
||||
];
|
||||
|
||||
const JAPANESE: &[(&str, &str, &str)] = &[
|
||||
("", "EffectCraft", "EffectCraft"),
|
||||
("app.about", "About EffectCraft...", "EffectCraftについて..."),
|
||||
@@ -725,25 +1405,30 @@ mod tests {
|
||||
for mac in [false, true] {
|
||||
keys(&parse(TREE, mac).unwrap(), &mut actual);
|
||||
}
|
||||
let mut unique = BTreeSet::new();
|
||||
for (command, en, ja) in JAPANESE {
|
||||
let key = (command.to_string(), en.to_string());
|
||||
assert!(actual.contains(&key), "stale translation: {key:?}");
|
||||
assert!(unique.insert(key), "duplicate translation: {command} / {en}");
|
||||
assert!(!ja.is_empty());
|
||||
}
|
||||
// All fixed TREE entries are covered; @effects is a generated plug-in catalog,
|
||||
// whose product/effect names are intentionally left as registered.
|
||||
for line in TREE.lines() {
|
||||
let line = line.trim().trim_start_matches("[mac] ").trim_start_matches("[!mac] ");
|
||||
if line.is_empty() || line == "---" || line.starts_with('@') {
|
||||
continue;
|
||||
let mut japanese_keys = BTreeSet::new();
|
||||
let mut chinese_keys = BTreeSet::new();
|
||||
for (catalog, unique) in [(JAPANESE, &mut japanese_keys), (SIMPLIFIED_CHINESE, &mut chinese_keys)] {
|
||||
for (command, en, translated) in catalog {
|
||||
let key = (command.to_string(), en.to_string());
|
||||
assert!(actual.contains(&key), "stale translation: {key:?}");
|
||||
assert!(unique.insert(key), "duplicate translation: {command} / {en}");
|
||||
assert!(!translated.is_empty());
|
||||
}
|
||||
// All fixed TREE entries are covered; @effects is a generated plug-in catalog,
|
||||
// whose product/effect names are intentionally left as registered.
|
||||
for line in TREE.lines() {
|
||||
let line = line.trim().trim_start_matches("[mac] ").trim_start_matches("[!mac] ");
|
||||
if line.is_empty() || line == "---" || line.starts_with('@') {
|
||||
continue;
|
||||
}
|
||||
let mut parts = line.split(" | ");
|
||||
let en = parts.next().unwrap();
|
||||
let command = parts.next().and_then(|p| p.split_whitespace().next()).unwrap_or("");
|
||||
assert!(unique.contains(&(command.into(), en.into())), "untranslated fixed entry: {line}");
|
||||
}
|
||||
let mut parts = line.split(" | ");
|
||||
let en = parts.next().unwrap();
|
||||
let command = parts.next().and_then(|p| p.split_whitespace().next()).unwrap_or("");
|
||||
assert!(unique.contains(&(command.into(), en.into())), "untranslated fixed entry: {line}");
|
||||
}
|
||||
// Every translated language covers exactly the same entries.
|
||||
assert_eq!(japanese_keys, chinese_keys, "the languages must translate the same entries");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -782,6 +1467,14 @@ mod tests {
|
||||
(Some("ja-JP"), "ja"),
|
||||
(Some("ja"), "ja"),
|
||||
(Some("JA_jp.UTF-8"), "ja"),
|
||||
(Some("zh-CN"), "zh-hans"),
|
||||
(Some("zh"), "zh-hans"),
|
||||
(Some("zh_CN.UTF-8"), "zh-hans"),
|
||||
(Some("zh-Hans-CN"), "zh-hans"),
|
||||
(Some("zh-SG"), "zh-hans"),
|
||||
(Some("zh-TW"), "en"),
|
||||
(Some("zh-Hant"), "en"),
|
||||
(Some("zh-HK"), "en"),
|
||||
(Some("en-US"), "en"),
|
||||
(Some("jv-ID"), "en"),
|
||||
(Some("de-DE"), "en"),
|
||||
@@ -792,8 +1485,64 @@ mod tests {
|
||||
let mut app = EffectcraftApp::new(effectcraft_engine::Session::default());
|
||||
assert_eq!(app.session.prefs.general.language, "system", "the default");
|
||||
assert_eq!(japanese(&app), system_language() == "ja");
|
||||
assert_eq!(chinese(&app), system_language() == "zh-hans");
|
||||
app.session.execute("prefs.set", json!({"key":"general.language", "value":"ja"})).unwrap();
|
||||
assert!(japanese(&app));
|
||||
app.session.execute("prefs.set", json!({"key":"general.language", "value":"zh-hans"})).unwrap();
|
||||
assert!(chinese(&app));
|
||||
assert!(!japanese(&app));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_chinese_entry_keeps_the_english_shape() {
|
||||
for (command, en, zh) in SIMPLIFIED_CHINESE {
|
||||
assert_eq!(en.contains("..."), zh.contains("..."), "{command} / {en}: {zh}");
|
||||
let brackets = |s: &str| s.chars().filter(|c| *c == '(' || *c == ')').count();
|
||||
assert_eq!(brackets(en), brackets(zh), "{command} / {en}: {zh}");
|
||||
assert!(!zh.contains(" "), "{command} / {en}: {zh}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zh_hans_translates_labels_computed_titles_and_keeps_names_verbatim() {
|
||||
let mut app = EffectcraftApp::new(effectcraft_engine::Session::default());
|
||||
app.session.execute("prefs.set", json!({"key":"general.language", "value":"zh-hans"})).unwrap();
|
||||
assert_eq!(language(&app), "zh-hans");
|
||||
assert!(chinese(&app));
|
||||
assert!(!japanese(&app));
|
||||
// Fixed menu rows come from the catalog.
|
||||
assert_eq!(label(&app, "", "Composition"), "合成");
|
||||
assert_eq!(label(&app, "", "Effect"), "效果");
|
||||
assert_eq!(label(&app, "comp.new", "New Composition..."), "新建合成...");
|
||||
assert_eq!(label(&app, "layer.newText", "Text"), "文本");
|
||||
// Untranslated keys and dynamic labels stay verbatim.
|
||||
assert_eq!(label(&app, "unknown.command", "Text"), "Text");
|
||||
assert_eq!(
|
||||
entry(&app, &MenuEntry { label: "Undo".into(), command: "edit.undo".into(), params: json!({}), shortcut: None }, "Undo Comp1".into()),
|
||||
"无可撤销的操作"
|
||||
);
|
||||
assert_eq!(
|
||||
entry(
|
||||
&app,
|
||||
&MenuEntry { label: "Layer".into(), command: "window.panel".into(), params: json!({"panel":"layer"}), shortcut: None },
|
||||
"Layer: File".into()
|
||||
),
|
||||
"图层: File"
|
||||
);
|
||||
// The submenu titles that name the current workspace / view.
|
||||
assert_eq!(
|
||||
submenu(&app, "Assign Shortcut to Workspace", "Assign Shortcut to “Default” Workspace".into()),
|
||||
"为工作区“Default”指定快捷键"
|
||||
);
|
||||
assert_eq!(submenu(&app, "Assign Shortcut to 3D View", "Assign Shortcut to “Top”".into()), "为 3D 视图“Top”指定快捷键");
|
||||
// The menu tree carries the same commands and shortcuts with the Chinese labels.
|
||||
let zh = crate::native_menu::build(&app);
|
||||
assert!(zh.items().iter().any(|i| i.command == "comp.new" && i.label == "新建合成..."));
|
||||
assert!(zh.items().iter().any(|i| i.command == "layer.newText" && i.label == "文本"));
|
||||
assert!(zh.items().iter().any(|i| i.command == "keys.easyEase" && i.label == "缓动"));
|
||||
// A dynamic filename is never translated.
|
||||
app.session.prefs.push_recent("/tmp/File.ecproj");
|
||||
assert!(crate::native_menu::build(&app).items().iter().any(|i| i.command == "file.openRecent" && i.label == "File.ecproj"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -184,7 +184,14 @@ pub fn build(app: &EffectcraftApp) -> NativeMenu {
|
||||
if role == Role::Hide && !services_added {
|
||||
out.push(NativeNode::Predefined {
|
||||
role: Role::Services,
|
||||
label: if crate::i18n::japanese(app) { "サービス" } else { "Services" }.into(),
|
||||
label: if crate::i18n::japanese(app) {
|
||||
"サービス"
|
||||
} else if crate::i18n::chinese(app) {
|
||||
"服务"
|
||||
} else {
|
||||
"Services"
|
||||
}
|
||||
.into(),
|
||||
command: String::new(),
|
||||
});
|
||||
out.push(NativeNode::Separator);
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ Commands (CLI, MCP, control channel):
|
||||
|
||||
### Settings that change behaviour
|
||||
|
||||
- `general.language`: interface language (`system` / `en` / `ja`), Settings ▸ General ▸ Language; menu labels change immediately. `system` (Match System, the default) follows the operating system's interface language where EffectCraft has a translation and is English otherwise; the browser build stays in English with it. Native Japanese UI uses installed system fonts; the web host must supply a Japanese font.
|
||||
- `general.language`: interface language (`system` / `en` / `ja` / `zh-hans`), Settings ▸ General ▸ Language; menu labels change immediately. `system` (Match System, the default) follows the operating system's interface language where EffectCraft has a translation and is English otherwise (a Chinese locale with a Traditional script or region among them); the browser build stays in English with it. Native Japanese and Simplified Chinese UI uses installed system fonts; the web host must supply a Japanese font.
|
||||
- `general.undoLevels`: Levels of Undo
|
||||
- `general.pathPointSize`: Path Point and Handle Size
|
||||
- `general.recentItems`: Recent Projects Shown
|
||||
|
||||
Reference in New Issue
Block a user