mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-31 15:48:33 +00:00
Merge pull request #2054 from midasdf/jp/ja-dialogs
i18n(ja): panels and dialogs (27% → 39%)
This commit is contained in:
11 files changed
+1043
-61
No files matched your search
+18
-11
@@ -2,7 +2,7 @@
|
||||
|
||||
**Stage: alpha** · next: beta, ~30 points of "ready for real work" and ~350–620 h away
|
||||
|
||||
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-12 · **Change:** minor (open-issue count, crash list and localization share re-audited against `upstream/main` 470ea7a3) · **Target:** Adobe After Effects 2026 (26.5.0.89)
|
||||
> **Last reviewed:** 2026-10-22 · **Last updated:** 2026-10-30 · **Change:** minor (localization: 303 more panel/dialog rows in Japanese and the Chinese catalogs; recounted after #1774: Japanese 27% → 46%, Simplified Chinese 29% → 46%, Traditional Chinese 29% → 38%, overall 18% → 24%) · **Target:** Adobe After Effects 2026 (26.5.0.89)
|
||||
|
||||
EffectCraft aims to do what After Effects does, with the same panels, menus and behaviour, written
|
||||
from scratch in Rust. This page is the one-page summary; the evidence is in
|
||||
@@ -51,7 +51,7 @@ Linux/Windows reliability (30–50 h) and depth in animation, masks, effects and
|
||||
| UI/UX fidelity | 65% | 60–120 | [ui-parity.md](docs/ui-parity.md) |
|
||||
| File formats | 50% | 130–230 | [file-format-parity.md](docs/file-format-parity.md) |
|
||||
| Hardware | 40% | 60–120 | [hardware-parity.md](docs/hardware-parity.md) |
|
||||
| Localization | 18% | 60–110 + review | [localization-parity.md](docs/localization-parity.md) |
|
||||
| Localization | 24% | 60–110 + review | [localization-parity.md](docs/localization-parity.md) |
|
||||
| Performance | 35% | 50–100 | [gaps.md](docs/gaps.md#g5-performance-at-real-world-scale) |
|
||||
| Stability | 45% | 40–80 | [gaps.md](docs/gaps.md#g3-stability-and-a-green-main) |
|
||||
| Platforms | 65% | 30–60 | [gaps.md](docs/gaps.md#g2-real-user-reliability-on-every-platform) |
|
||||
@@ -80,24 +80,24 @@ Weights and evidence per row: [target-app-parity.md](docs/target-app-parity.md#b
|
||||
|
||||
## Languages
|
||||
|
||||
UI strings translated out of ≈ 3,900 (detail: [localization-parity.md](docs/localization-parity.md)).
|
||||
UI strings translated out of ≈ 4,200 (detail: [localization-parity.md](docs/localization-parity.md)).
|
||||
|
||||
| Language | Status | % |
|
||||
|---|---|---:|
|
||||
| English | full | 100% |
|
||||
| Simplified Chinese | partial (menus, part of the panels) | 29% |
|
||||
| Spanish | menus only | 16% |
|
||||
| Simplified Chinese | partial (menus, most of the panels) | 46% |
|
||||
| Spanish | menus only | 29% |
|
||||
| Hindi | none | 0% |
|
||||
| Arabic | none | 0% |
|
||||
| French | menus only | 16% |
|
||||
| Portuguese (Brazil) | partial (menus, part of the panels) | 26% |
|
||||
| Portuguese (Brazil) | partial (menus, part of the panels) | 34% |
|
||||
| Indonesian | none | 0% |
|
||||
| Japanese | partial (menus, part of the panels) | 27% |
|
||||
| Japanese | partial (menus, most of the panels) | 46% |
|
||||
| German | menus only | 16% |
|
||||
| Korean | none | 0% |
|
||||
| Vietnamese | none | 0% |
|
||||
|
||||
Also shipped: Traditional Chinese (partial, 29%), Ukrainian (partial, 29%), Czech (partial, 29%), Georgian (partial, 38%; native-speaker reviewed) and Russian (menus only, 16%). No other language has had
|
||||
Also shipped: Traditional Chinese (partial, 38%), Ukrainian (partial, 29%), Czech (partial, 29%), Polish (partial, 34%), Georgian (partial, 39%; native-speaker reviewed) and Russian (menus only, 15%). No other language has had
|
||||
native-speaker review.
|
||||
|
||||
## Upcoming
|
||||
@@ -125,10 +125,17 @@ Come tell us what matters most to you on [Discord](https://discord.gg/artcraft).
|
||||
rotation of the paths above it by random amounts that change over time, up to the Transform
|
||||
values it holds. The copies of a Repeater above it wiggle independently as far as its
|
||||
Correlation allows; with the Repeater below it, they wiggle together.
|
||||
- 2026-10-22: Localization: the panel/dialog catalogs gain 303 rows in Japanese, Simplified
|
||||
Chinese and Traditional Chinese — panel tabs, form and dialog labels, panel context menus,
|
||||
tracker/graph/text-panel controls, File-panel footers and credits. Recounted after #1774:
|
||||
Japanese is 1,923 of ≈ 4,200 interface strings (46%, with 297 effect names); the Chinese
|
||||
panel catalogs hold 998 (Simplified) and 951 (Traditional) rows, and Simplified Chinese is
|
||||
46% with its 307 effect names; the overall share is ≈ 24%.
|
||||
- 2026-10-16: Convert To Bezier Path turns a shape layer's Rectangle, Ellipse or Polystar
|
||||
path into an editable Path 1 with the same geometry, as After Effects does; it used to
|
||||
apply to mask RotoBezier only, so a parametric shape path could not be converted at all
|
||||
and its vertices could not be edited or animated (#932).
|
||||
- 2026-10-14: Georgian (`ka`): every menu row, every panel-catalog row the Chinese catalogs have plus 195 Georgian-only ones, and the effect names and categories; Match System for `ka` / `ka-GE` / `ka_GE.UTF-8` locales. Reviewed by a native speaker.
|
||||
- 2026-10-12: Roto Brush span edits report strokes outside a trimmed layer without panicking;
|
||||
strokes and undo history are preserved so restoring the timing allows the span edit again.
|
||||
- 2026-10-11: Ukrainian panels caught up with the Chinese catalogs. The 95 rows the panel
|
||||
@@ -143,7 +150,6 @@ Come tell us what matters most to you on [Discord](https://discord.gg/artcraft).
|
||||
follow the shared standard: `docs/parity.md` became `docs/target-app-parity.md`; new
|
||||
`docs/roadmap.md`, `localization-parity.md`, `file-format-parity.md`, `hardware-parity.md`,
|
||||
`ui-parity.md`, `effects-parity.md` and `scripting-parity.md`.
|
||||
- 2026-10-14: Georgian (`ka`): every menu row, every panel-catalog row the Chinese catalogs have plus 195 Georgian-only ones, and the effect names and categories; Match System for `ka` / `ka-GE` / `ka_GE.UTF-8` locales. Reviewed by a native speaker.
|
||||
- 2026-10-10: Spanish (#460) and Brazilian Portuguese (#217) menu translations.
|
||||
- 2026-10-10: Japanese now translates the interface below the menu bar too: `crates/ui-egui/src/i18n/ui.rs` has a Japanese table with the same 396 rows as the Chinese ones (panels, dialogs, buttons and tooltips; the shape test keeps the three catalogs listing the same source strings). Menus were already Japanese.
|
||||
- 2026-10-09: Ukrainian now covers all 396 current panel-catalog strings, including dialogs, buttons and tooltips, alongside its menu translation. The catalog keeps the same source keys and placeholder counts as the Chinese catalogs; missing or engine-generated text still falls back to English.
|
||||
@@ -163,11 +169,12 @@ Come tell us what matters most to you on [Discord](https://discord.gg/artcraft).
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-22 | minor | Localization: 300 more panel/dialog rows in Japanese and the Chinese catalogs, plus the review's three missing rows (Basic, Advanced, Play/Stop) — panel tabs, form and dialog labels, context menus, tracker/graph/text-panel controls, File-panel footers, credits; language shares recounted after #1774 (Japanese 27% → 46% with 297 effect names, Simplified Chinese 29% → 46% with 307 effect names, Traditional Chinese 29% → 38%, overall 18% → 24%) |
|
||||
| 2026-10-12 | minor | Open-issue count (134 to 216), crash list and localization share (12% to 18%) updated to match docs/gaps.md |
|
||||
| 2026-10-12 | patch | Roto Brush span validation after trimming; command regressions for both layer edges |
|
||||
| 2026-10-12 | minor | Shared PDF object/xref parsing with bounded app-owned conversion and preserved stream budgets; drawing, EPS and image/font policy remain unchanged |
|
||||
| 2026-10-10 | minor | Hours to ≈ 95% for each audience |
|
||||
| 2026-10-10 | minor | Headline adds mainstream practitioner (≈ 47%) and essentials user (≈ 52%) |
|
||||
| 2026-10-12 | minor | Shared PDF object/xref parsing with bounded app-owned conversion and preserved stream budgets; drawing, EPS and image/font policy remain unchanged |
|
||||
| 2026-10-10 | minor | Stage checked against the new core-workflow gate (all six pass; still alpha) |
|
||||
| 2026-10-10 | major | Rewritten to the shared progress-docs standard: stage, two numbers, dimensions, features, languages, upcoming, progress log; milestones moved to docs/roadmap.md |
|
||||
| 2026-10-10 | minor | Stage checked against the new core-workflow gate (all six pass; still alpha) |
|
||||
| 2026-10-05 | major | Two numbers (breadth vs real use) and workstreams G1–G9 |
|
||||
@@ -246,7 +246,7 @@ pub fn contributors_ui(ui: &mut egui::Ui, auto: &mut Registry) {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
ui.label(tr("Show"));
|
||||
for m in NameMode::ALL {
|
||||
let r = ui.selectable_label(v.names == m, m.label());
|
||||
let r = ui.selectable_label(v.names == m, tr(m.label()));
|
||||
auto.add(&format!("about.credits.show.{}", m.id()), r.rect, m.label());
|
||||
if r.clicked() {
|
||||
v.names = m;
|
||||
@@ -254,9 +254,9 @@ pub fn contributors_ui(ui: &mut egui::Ui, auto: &mut Registry) {
|
||||
}
|
||||
ui.separator();
|
||||
ui.label(tr("Sort"));
|
||||
let combo = craft_ui::ComboBox::from_id_salt("credits_sort").selected_text(v.key.label().0).show_ui(ui, |ui| {
|
||||
let combo = craft_ui::ComboBox::from_id_salt("credits_sort").selected_text(tr(v.key.label().0)).show_ui(ui, |ui| {
|
||||
for k in SortKey::ALL {
|
||||
let r = ui.selectable_label(v.key == k, k.label().0);
|
||||
let r = ui.selectable_label(v.key == k, tr(k.label().0));
|
||||
auto.add(&format!("about.credits.sort.{}", k.id()), r.rect, k.label().0);
|
||||
if r.clicked() {
|
||||
v.key = k;
|
||||
@@ -309,7 +309,7 @@ fn table(ui: &mut egui::Ui, list: &[&Contributor], v: &mut View, auto: &mut Regi
|
||||
egui::Grid::new("credits_table").striped(true).num_columns(SortKey::ALL.len()).show(ui, |ui| {
|
||||
for k in SortKey::ALL {
|
||||
let arrow = if v.key == k { if v.ascending { " ▲" } else { " ▼" } } else { "" };
|
||||
let r = ui.button(RichText::new(format!("{}{arrow}", k.label().1)).strong()).on_hover_text(k.label().0);
|
||||
let r = ui.button(RichText::new(format!("{}{arrow}", k.label().1)).strong()).on_hover_text(tr(k.label().0));
|
||||
auto.add(&format!("about.credits.header.{}", k.id()), r.rect, k.label().0);
|
||||
if r.clicked() {
|
||||
if v.key == k {
|
||||
|
||||
@@ -7536,6 +7536,19 @@ mod tests {
|
||||
println!("total: {total}");
|
||||
}
|
||||
|
||||
/// Prints the translated-row counts per language, the numbers `docs/localization-parity.md`
|
||||
/// quotes. `cargo xtask i18n-report` runs it with `--nocapture`.
|
||||
#[test]
|
||||
fn catalog_row_counts_report() {
|
||||
println!("Localization catalog rows:");
|
||||
for code in CATALOG_CODES {
|
||||
let menus = menu_catalog(code).map_or(0, |catalog| catalog.len());
|
||||
let panels = ui::translated_rows(code);
|
||||
let effect_names = effects::translated_rows(code);
|
||||
println!("{code}: menus {menus}, panels {panels}, effect names {effect_names}, total {}", menus + panels + effect_names);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn menu_catalogs_have_no_stale_or_duplicate_rows() {
|
||||
let mut actual = BTreeSet::new();
|
||||
|
||||
@@ -87,6 +87,13 @@ pub(crate) fn name(id: &str, english: &str) -> String {
|
||||
catalog(current()).and_then(|c| c.row(id)).map_or_else(|| english.to_string(), |(_, translated)| translated.to_string())
|
||||
}
|
||||
|
||||
/// The number of effect-name rows `language` translates, for the row-count report; 0 when it has
|
||||
/// no catalog or when it is English.
|
||||
#[cfg(test)]
|
||||
pub(super) fn translated_rows(language: &str) -> usize {
|
||||
catalog(language).map_or(0, |c| c.rows.len())
|
||||
}
|
||||
|
||||
/// The name to draw for an effect group the property tree stores as `stored`: the catalog name,
|
||||
/// plus the instance index the engine appends to a repeat (`Gaussian Blur 2` → `高斯模糊 2`).
|
||||
///
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -233,7 +233,7 @@ impl ButtonBar {
|
||||
let chosen = widgets::popup_list(ui, pid, pos, r, rows, 0, |ui| {
|
||||
let mut chosen = None;
|
||||
for (id, label, on, tip) in &self.hidden {
|
||||
let item = ui.selectable_label(*on, label.as_str()).on_hover_text(tip.as_str());
|
||||
let item = ui.selectable_label(*on, crate::i18n::tr(label)).on_hover_text(crate::i18n::tr(tip));
|
||||
app.auto.add(&format!("timeline.graph.more.{id}"), item.rect, tip);
|
||||
if item.clicked() {
|
||||
chosen = Some(id.clone());
|
||||
@@ -263,14 +263,16 @@ struct BarBtn<'a> {
|
||||
fn text_button(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painter, bar: &mut ButtonBar, y: f32, btn: BarBtn) -> bool {
|
||||
let BarBtn { label, on, id, tip } = btn;
|
||||
let t = app.tokens;
|
||||
let w = p.layout_no_wrap(label.to_string(), Tokens::ui(11.0), t.text).size().x + 14.0;
|
||||
let (shown, shown_tip) = (crate::i18n::tr(label), crate::i18n::tr(tip));
|
||||
let w = p.layout_no_wrap(shown.to_string(), Tokens::ui(11.0), t.text).size().x + 14.0;
|
||||
// Once one button overflows, the rest follow it into the menu (they keep their order).
|
||||
if !bar.hidden.is_empty() || bar.x + w > bar.limit {
|
||||
// The menu translates these English labels when it draws them; automation keeps them.
|
||||
bar.hidden.push((id.to_string(), label.to_string(), on, tip.to_string()));
|
||||
return bar.chosen.as_deref() == Some(id);
|
||||
}
|
||||
let r = Rect::from_min_size(pos2(bar.x, y - 9.0), vec2(w, 18.0));
|
||||
let resp = ui.interact(r, egui::Id::unique(("graph-btn", id)), Sense::click()).on_hover_text(tip);
|
||||
let resp = ui.interact(r, egui::Id::unique(("graph-btn", id)), Sense::click()).on_hover_text(shown_tip);
|
||||
p.rect_filled(
|
||||
r,
|
||||
3.0,
|
||||
@@ -282,7 +284,7 @@ fn text_button(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painter, b
|
||||
Color32::from_rgb(0x2c, 0x2c, 0x2c)
|
||||
},
|
||||
);
|
||||
p.text(r.center(), Align2::CENTER_CENTER, label, Tokens::ui(11.0), if on { Color32::WHITE } else { t.text });
|
||||
p.text(r.center(), Align2::CENTER_CENTER, shown, Tokens::ui(11.0), if on { Color32::WHITE } else { t.text });
|
||||
app.auto.add(&format!("timeline.graph.{id}"), r, tip);
|
||||
bar.x += w + 4.0;
|
||||
resp.clicked()
|
||||
|
||||
@@ -43,7 +43,10 @@ pub fn preview(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
|
||||
for (icon, cmd, tip) in buttons {
|
||||
let r = Rect::from_min_size(pos2(x, y), vec2(bw, 28.0));
|
||||
let icon = if cmd == "playback.toggle" && app.playback.playing { Icon::Pause } else { icon };
|
||||
if widgets::icon_button(ui, r, icon, cmd == "playback.toggle" && app.playback.playing, &t, egui::Id::unique(("pv", cmd))).on_hover_text(tip).clicked() {
|
||||
if widgets::icon_button(ui, r, icon, cmd == "playback.toggle" && app.playback.playing, &t, egui::Id::unique(("pv", cmd)))
|
||||
.on_hover_text(tr(tip))
|
||||
.clicked()
|
||||
{
|
||||
// The play button plays with the options of the shortcut shown below.
|
||||
let params = if cmd == "playback.toggle" { json!({"shortcut": current.id()}) } else { json!({}) };
|
||||
let _ = crate::menus::invoke(app, &ctx, cmd, params);
|
||||
|
||||
@@ -812,7 +812,7 @@ fn footer(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painter, foot:
|
||||
(Icon::NewComp, "newComp", "Create a new Composition"),
|
||||
] {
|
||||
let r = Rect::from_min_size(pos2(x, foot.min.y + 3.0), vec2(22.0, 22.0));
|
||||
let resp = widgets::icon_button(ui, r, icon, false, &t, egui::Id::unique(("pfoot", id))).on_hover_text(tip);
|
||||
let resp = widgets::icon_button(ui, r, icon, false, &t, egui::Id::unique(("pfoot", id))).on_hover_text(crate::i18n::tr(tip));
|
||||
app.auto.add(&format!("project.{id}"), r, tip);
|
||||
resp.widget_info(|| egui::WidgetInfo::labeled(egui::Role::Button, true, crate::i18n::tr(tip)));
|
||||
if resp.clicked() {
|
||||
|
||||
@@ -626,7 +626,7 @@ pub fn apply_dialog(app: &mut EffectcraftApp, ctx: &egui::Context, t: &Tokens) {
|
||||
super::dialogs::modal(ctx, "Motion Tracker Apply Options", vec2(380.0, 170.0), t, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(crate::i18n::tr("Apply Dimensions:"));
|
||||
let labels = ["X and Y", "X only", "Y only"];
|
||||
let labels = [crate::i18n::tr("X and Y"), crate::i18n::tr("X only"), crate::i18n::tr("Y only")];
|
||||
let r = craft_ui::ComboBox::from_id_salt("track-apply-dims")
|
||||
.selected_text(labels[d.dims.min(2)])
|
||||
.show_ui(ui, |ui| {
|
||||
|
||||
+44
-37
@@ -1,6 +1,6 @@
|
||||
# Localization parity
|
||||
|
||||
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-23 · **Change:** minor (Georgian: menus, panels and effect names; missing strings show in English; `missing_translations_report` lists them) · **Target:** Adobe After Effects 2026
|
||||
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-30 · **Change:** minor (recounted at this tree after #1774: Japanese 1,923 of ≈ 4,200 interface strings (46%, with 297 effect names), Simplified Chinese 1,935 (46%, with 307 effect names), Traditional Chinese 1,581 (38%, its panel catalog 951 rows after #2244); overall ≈ 24%; previously: minor, the panel/dialog catalogs grow by 303 rows in Japanese, Simplified Chinese and Traditional Chinese: panel tabs, form and dialog labels, context menus, tracker/graph/text-panel labels, credits and File-panel footers; previously: minor, catalogs recounted at `upstream/main` 470ea7a3: menus in 10 languages, panels in 6, Hangul probe (#599)) · **Target:** Adobe After Effects 2026
|
||||
|
||||
How much of EffectCraft's interface is translated, language by language, compared with After
|
||||
Effects. [gaps.md](gaps.md) gap 16 and workstream G9 hold the work;
|
||||
@@ -17,28 +17,31 @@ interface; Arabic and Hebrew text *in layers* is supported through its Middle Ea
|
||||
## How EffectCraft translates
|
||||
|
||||
- **Menus:** `crates/ui-egui/src/i18n.rs`, one catalog per language keyed by
|
||||
`(command, English label)` (624 catalog rows each at 470ea7a3, counted). A test
|
||||
(`menu_catalogs_have_no_stale_or_duplicate_rows`) fails on a row whose entry left the menu tree
|
||||
or on a repeated row. The generated Effect menu is not part of that fixed tree: its entries
|
||||
and category submenus take their labels from the effect catalog below.
|
||||
`(command, English label)`. A test (`menu_catalogs_have_no_stale_or_duplicate_rows`) fails on a
|
||||
row whose entry left the menu tree or on a repeated row, so every catalog covers all fixed
|
||||
entries (630 catalog rows each at this tree, counted; 629 in Georgian). The generated Effect menu is not part of
|
||||
that fixed tree: its entries and category submenus take their labels from the effect catalog
|
||||
below.
|
||||
- **Panels, dialogs, buttons, tooltips:** `crates/ui-egui/src/i18n/ui.rs`, keyed by the English
|
||||
source string, with English fallback. Catalogs exist for Japanese (693 rows), Simplified and
|
||||
Traditional Chinese (695 and 648 since #2244 pruned the Traditional one), Ukrainian (524),
|
||||
Brazilian Portuguese (695) and Czech (518), counted at this tree. Georgian has every row the
|
||||
Simplified Chinese catalog has, plus 191 for panels converted to the catalog.
|
||||
source string, with English fallback. Catalogs exist for Japanese (996 rows), Simplified
|
||||
Chinese (998), Traditional Chinese (951, after #2244 pruned the table), Ukrainian (524),
|
||||
Brazilian Portuguese (695), Czech (518) and Spanish (513); counted at this tree. Georgian has
|
||||
the Simplified Chinese catalog's 694 rows, plus 191 for panels converted to the catalog since
|
||||
(885 in all).
|
||||
- **Effect names:** `crates/ui-egui/src/i18n/effects.rs`, keyed by **effect id**, in Simplified
|
||||
Chinese and Georgian (307 rows, one per effect in the registry, plus its 21 categories). The registry's
|
||||
Chinese (307 rows, one per effect in the registry), Japanese (297 of the 307 ids) and Georgian
|
||||
(307 rows, plus its 21 categories). The registry's
|
||||
English name stays the effect's identity: `effect.list`, `effect.apply {"effect": …}`, scripts
|
||||
and expressions match on it, and the property tree stores it as the effect group's name. Only
|
||||
the drawing — the Effect menu, Effect Controls, the Timeline and Effects & Presets — goes
|
||||
through the catalog, so a project file is identical whichever interface language opens it.
|
||||
A repeat (`Gaussian Blur 2`) keeps the index the engine appends, and a group the user renamed
|
||||
in Effect Controls stays verbatim. Adding a language there is two tables and one arm, and no
|
||||
panel changes: Traditional Chinese and Japanese have their tables in place and empty, so those
|
||||
languages draw English until a translator fills them (the Japanese set for #821 is what that
|
||||
slot is for). Each language decides for itself which names stay English — Adobe's Japanese
|
||||
interface leaves the `CC`, `VR` and `OCIO` sets in English while its Chinese one translates
|
||||
them — so a row repeating the English name is a choice, not a missing row.
|
||||
panel changes: Traditional Chinese has its table in place and empty, and Japanese fills 297 of
|
||||
the 307 ids, so the rest draw English until a translator completes them. Each language decides
|
||||
for itself which names stay English — Adobe's Japanese interface leaves the `CC`, `VR` and
|
||||
`OCIO` sets in English while its Chinese one translates them — so a row repeating the English
|
||||
name is a choice, not a missing row.
|
||||
- **Missing strings:** a string with no row in the interface language shows in English, and no
|
||||
test, build or release fails on a missing translation. The `missing_translations_report` test
|
||||
(`crates/ui-egui/src/i18n.rs`) prints, per language, the fixed menu entries, panel strings, effect
|
||||
@@ -60,25 +63,27 @@ interface; Arabic and Hebrew text *in layers* is supported through its Middle Ea
|
||||
|
||||
## Measurement
|
||||
|
||||
Measured 10 October 2026 at `origin/main` 1446e27 and recounted on 12 October at `upstream/main`
|
||||
470ea7a3 by counting catalog rows (`const` tables in `crates/ui-egui/src/i18n.rs` and
|
||||
`i18n/ui.rs`; menu rows 624 per language, so the share is computed from 624 rather than 618). The
|
||||
denominator, **≈ 3,900 user-visible strings**, was estimated on 10 October and is kept: 618 fixed menu entries + ≈ 1,320 capitalised UI
|
||||
literals in `crates/ui-egui/src` outside tests and catalogs (a regex count, so an upper bound) +
|
||||
≈ 1,650 distinct effect parameter names + 306 effect names. Engine messages are not counted, so
|
||||
the true percentages are slightly lower.
|
||||
Measured 10 October 2026 at `origin/main` 1446e27, recounted on 22 October 2026 at `ad8b6acb`,
|
||||
and recounted again at this tree after #1774 by counting catalog rows (`const` tables in
|
||||
`crates/ui-egui/src/i18n.rs`, `i18n/ui.rs` and `i18n/effects.rs`: 630 menu rows, 998
|
||||
panel/dialog sources in Simplified Chinese, 951 in Traditional Chinese and 996 in Japanese). The
|
||||
denominator, **≈ 4,200 user-visible strings**, is a rounded estimate: the 630 fixed menu entries,
|
||||
the 998 panel/dialog sources, 307 effect names, ≈ 1,650 distinct effect parameter names and
|
||||
≈ 620 other unwrapped interface strings (Home screen literals, engine-built tooltips, error and
|
||||
status messages). It counts distinct strings, not catalog rows; engine messages are only partly
|
||||
counted, so the true percentages are slightly lower.
|
||||
|
||||
| Language | Code | UI strings translated | Dialogs / tooltips / help | Script support | Native review | Status | To `full` |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| English | `en` | ≈ 3,900 (100%, source) | All; docs in English | — | yes | full | — |
|
||||
| Simplified Chinese | `zh-hans` | 1,324 (≈ 34%): menus 629 rows, panels 695 | Panels and dialogs at the zh source list; no help, effect names translated (307) and their parameter names not; Home screen literals unwrapped (#574, closed) | System CJK fallback; Han follows the UI language; CJK text in comps renders wrongly (#453); IME in text layers | no | partial | 6–9 h + review |
|
||||
| English | `en` | ≈ 4,200 (100%, source) | All; docs in English | — | yes | full | — |
|
||||
| Simplified Chinese | `zh-hans` | 1,935 (≈ 46%): menus 630 rows, panels 998, effect names 307 | Panels and dialogs partly; no help, effect names translated and their parameter names not; Home screen literals unwrapped (#574, closed) | System CJK fallback; Han follows the UI language; CJK text in comps renders wrongly (#453); IME in text layers | no | partial | 6–9 h + review |
|
||||
| Spanish | `es` | 1,142 (≈ 29%): menus 629 rows, panels 513 | Menus only; the panel catalog from #996 | Latin, fine | no | partial | 9–12 h + review |
|
||||
| Hindi | `hi` | 0 | — | UI: Devanagari fallback font but no shaping; text layers shape Devanagari | no | none (After Effects: none) | 9–13 h + shaping in the UI |
|
||||
| Arabic | `ar` | 0 | — | UI: Arabic fallback font but no shaping and no RTL layout; text layers: bidi + shaping | no | none (After Effects: none) | 9–13 h + 15–25 h RTL UI |
|
||||
| French | `fr` | 624 (≈ 16%) | Menus only | Latin, fine | no | menus only | 7–10 h + review |
|
||||
| Portuguese (Brazil) | `pt-br` | 1,324 (≈ 34%): menus 629 rows, panels 695 | Panels and dialogs at the Chinese catalogs' source list; the six keys main added after that count are translated too; AI-assisted, not yet native-speaker proofread | Latin, fine | no | partial | independent native review |
|
||||
| Indonesian | `id` | 0 | — | Latin, fine | no | none (After Effects: none) | 8–12 h + review |
|
||||
| Japanese | `ja` | 1,322 (≈ 34%): menus 629 rows, panels 693 | Panels and dialogs partly | Japanese system fallback; vertical text and Tate-Chu-Yoko in text layers; IME | no | partial | 6–9 h + review |
|
||||
| Japanese | `ja` | 1,923 (≈ 46%): menus 630 rows, panels 996, effect names 297 | Panels and dialogs partly; no help, effect names translated for 297 of the 307 ids and their parameter names not; Home screen literals unwrapped (#574, closed) | Japanese system fallback; vertical text and Tate-Chu-Yoko in text layers; IME | no | partial | 6–9 h + review |
|
||||
| German | `de` | 624 (≈ 16%) | Menus only (open PR #666 adds interface translations) | Latin, fine | no | menus only | 7–10 h + review |
|
||||
| Korean | `ko` | 0 | — | Hangul fallback probe added (#599, closed); not checked on macOS here | no | none | 9–13 h + review |
|
||||
| Vietnamese | `vi` | 0 | — | Latin with stacked diacritics; untested | no | none (After Effects: none) | 8–12 h + review |
|
||||
@@ -87,22 +92,22 @@ Other languages EffectCraft ships (4):
|
||||
|
||||
| Language | Code | UI strings translated | Status | To `full` |
|
||||
|---|---|---|---|---|
|
||||
| Traditional Chinese | `zh-hant` | 1,277 (≈ 33%): menus 629 rows, panels 648 | partial | 6–9 h + review |
|
||||
| Traditional Chinese | `zh-hant` | 1,581 (≈ 38%): menus 630 rows, panels 951 | partial | 6–9 h + review |
|
||||
| Ukrainian | `uk` | 1,153 (≈ 29%): menus 629 rows, panels 524 | partial | 6–9 h + review |
|
||||
| Czech | `cs` | 1,147 (≈ 29%): menus 629 rows, panels 518 | Existing catalog entries covered; unwrapped UI, effects and engine text still in English; AI-assisted, not yet native-speaker proofread | Remaining strings + independent native review |
|
||||
| Georgian | `ka` | 1,514 (≈ 39%): menus 628 rows, panels 886 (the Chinese catalogs' 695 plus 191 Georgian-only rows: form dialogs, context menus, column headers), effect names 307 + 21 categories; native-speaker reviewed | partial | 5–8 h |
|
||||
| Georgian | `ka` | 1,514 (≈ 39%): menus 629 rows, panels 885 (the Simplified Chinese catalog's 694 plus 191 Georgian-only rows: form dialogs, context menus, column headers), effect names 307 + 21 categories; native-speaker reviewed | partial | 5–8 h |
|
||||
|
||||
Russian (`ru`) has a menu catalog (624 rows, ≈ 16%); After Effects also ships Italian, which EffectCraft does not (8–12 h).
|
||||
Russian (`ru`) has a menu catalog (630 rows, ≈ 15%); After Effects also ships Italian, which EffectCraft does not (8–12 h).
|
||||
|
||||
**Overall: ≈ 21%**, the average coverage of After Effects' 10 non-English languages
|
||||
(Simplified Chinese, Traditional Chinese, Japanese and Brazilian Portuguese 34%, Spanish 29%,
|
||||
French, German and Russian 16%, Korean and Italian 0%; 212 / 10, was ≈ 12% on 10 October;
|
||||
Ukrainian (≈ 29%) and Czech (≈ 29%) are EffectCraft-only and stay out of that average). This is the localization row in
|
||||
[target-app-parity.md](target-app-parity.md#by-dimension).
|
||||
**Overall: ≈ 24%**, the average coverage of After Effects' 10 non-English languages
|
||||
(Simplified Chinese 46%, Traditional Chinese 38%, Japanese 46%, Brazilian Portuguese 34%,
|
||||
Spanish 29%, French, German and Russian 16%, Korean and Italian 0%; 241 / 10, was ≈ 21% on
|
||||
22 October; Ukrainian (≈ 29%) and Czech (≈ 29%) are EffectCraft-only and stay out of that
|
||||
average). This is the localization row in [target-app-parity.md](target-app-parity.md#by-dimension).
|
||||
|
||||
**Effort.** One-time work first: route parameter names and engine messages through
|
||||
a catalog, wrap the remaining panel literals, and add a Hangul probe (10–20 h). Then each language
|
||||
needs ≈ 2,900 more strings (≈ 5–9 h per language at the pace of #398 and #401). Parity with After
|
||||
needs ≈ 2,600 more strings (≈ 5–9 h per language at the pace of #398 and #401). Parity with After
|
||||
Effects' 10 non-English languages: **≈ 60–110 h**; the four extra languages of the standard list
|
||||
(Hindi, Arabic, Indonesian, Vietnamese) add ≈ 50–80 h, most of it right-to-left layout and
|
||||
complex shaping in the interface. Every language needs native-speaker review, which only a human
|
||||
@@ -112,9 +117,11 @@ can give; only Georgian, contributed by a native speaker (#1843), has had it.
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-30 | minor | Recounted on the merged tree after #1774: Japanese 1,923 (46%, 297 effect names), Simplified Chinese 1,935 (46%, 307 effect names), Traditional Chinese 1,581 (38%, 951 panel rows after #2244's prune); overall ≈ 24% |
|
||||
| 2026-10-22 | minor | Panel/dialog second step: 300 more catalog rows in Japanese, Simplified Chinese and Traditional Chinese, plus the three rows the review found missing (Basic, Advanced and Play/Stop) — panel tabs, form and dialog labels, panel context menus, the tracker and graph controls, text-panel options, File-panel footers and credits; the panel tables are now 996 Japanese and 998 Simplified Chinese rows, all drawn through `tr`/`tr_args`, with the tests keeping the three catalogs listing the same sources; the 30 October recount above carries the share |
|
||||
| 2026-10-18 | minor | Brazilian Portuguese completes its panel catalog (278 new rows, 417 → 695, the Chinese catalogs' source list); the doc recount closes the drift the batch merges left in every language's panel count; AI-assisted, not yet native-speaker proofread |
|
||||
| 2026-10-12 | minor | Recounted: Russian, French, German and Czech menus (#873, #987), Brazilian Portuguese and Czech panels (#830, #987), Hangul probe (#599); overall ≈ 12% to ≈ 18%; Korean and Italian still absent |
|
||||
| 2026-10-14 | minor | Georgian (`ka`): menus 628, panels 886 (191 Georgian-only, in `GEORGIAN_PANELS`), effect names and categories in `effects.rs` |
|
||||
| 2026-10-10 | major | First localization parity document: catalog rows counted for all six languages, the twelve-language table, After Effects' 11 shipped languages from its bundle |
|
||||
| 2026-10-11 | minor | Ukrainian panel catalog brought level with the Chinese ones (495 of 496 rows, counted at this commit); its share rises to ≈ 29%. The other languages' panel counts are the 10 October measurement |
|
||||
| 2026-10-13 | minor | Effect names and the generated Effect menu leave English: `i18n/effects.rs` adds 306 rows keyed by effect id (Simplified Chinese, from After Effects 2026's interface and Adobe's Chinese documentation for the `CC` series) and the 21 category names. Parameter names are still English; no other language has rows |
|
||||
| 2026-10-12 | minor | Recounted: Russian, French, German and Czech menus (#873, #987), Brazilian Portuguese and Czech panels (#830, #987), Hangul probe (#599); overall ≈ 12% to ≈ 18%; Korean and Italian still absent |
|
||||
| 2026-10-11 | minor | Ukrainian panel catalog brought level with the Chinese ones (495 of 496 rows, counted at this commit); its share rises to ≈ 29%. The other languages' panel counts are the 10 October measurement |
|
||||
| 2026-10-10 | major | First localization parity document: catalog rows counted for all six languages, the twelve-language table, After Effects' 11 shipped languages from its bundle |
|
||||
@@ -139,7 +139,7 @@ Feature depth (≈ 50%) feeds the overall *ready* number with the other dimensio
|
||||
| UI/UX fidelity | 65% | 60–120 | After Effects-shaped menus (587 entries), panels, workspaces, shortcuts; many interaction issues still open; multi-monitor only as separate panel windows (#486 open); Effect Controls not yet like 26.5's | [ui-parity.md](ui-parity.md) |
|
||||
| File formats | 50% | 130–230 | `.aep` / `.aepx` / `.mogrt` / `.ffx` can't be read; strong modern codecs (H.264, HEVC, AV1, VP9, ProRes) | [file-format-parity.md](file-format-parity.md) |
|
||||
| Hardware | 40% | 60–120 | wgpu GPU on Metal/Vulkan/Direct3D 12/WebGPU with CPU fallback; no hardware decode/encode; Direct3D 12 compositor fails (#613); no video-out hardware | [hardware-parity.md](hardware-parity.md) |
|
||||
| Localization | 18% | 60–110 + review | Average coverage of After Effects' 10 non-English languages (measured catalog rows over ≈ 3,900 strings): menus in 10 languages, panels in 6, effects in none; After Effects ships 11 languages fully | [localization-parity.md](localization-parity.md) |
|
||||
| Localization | 24% | 60–110 + review | Average coverage of After Effects' 10 non-English languages (measured catalog rows over ≈ 4,200 strings): menus in 10 languages, panels in 7, effects in Simplified Chinese and Japanese; After Effects ships 11 languages fully | [localization-parity.md](localization-parity.md) |
|
||||
| Performance | 35% | 50–100 | Internal numbers only; users report stutter and slow scrubbing | [gaps.md](gaps.md#g5-performance-at-real-world-scale) |
|
||||
| Stability | 45% | 40–80 | Open crash reports #580, #501, #426, #341, #234, #879 (#591, #306 and #511 are closed); no CI runs the tests on pull requests | [gaps.md](gaps.md#g3-stability-and-a-green-main) |
|
||||
| Platforms | 65% | 30–60 | Releases for macOS, Windows x64/x86/ARM64, Linux, FreeBSD and the web (more than After Effects), but Linux and Windows users hit basic bugs | [gaps.md](gaps.md#g2-real-user-reliability-on-every-platform) |
|
||||
|
||||
Reference in new issue
Block a user