mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-26 11:56:50 -06:00
Turkish interface (Türkçe) (#1529)
Add a Turkish catalog (tr.tsv, 1,330 rows): the union of the existing catalogs, four menu headings (Ölçülendirme for the Dimension menu, Ölçü for the object) and single-form counts, since a Turkish noun stays singular after a number. No marked UI literal falls back to English. Prompts read "… girin" for Enter and "… belirtin" for Specify; clickable keywords (Top, Zero, Bottom, _tan to, nX/nXP) keep the spelling the engine accepts. Register the language (Preference::Turkish, `tr`, Türkçe) and add locale, preference, count, menu-heading, live-switch, dialog and font tests. Docs, README and ATTRIBUTION list it; the translation is AI-assisted, the running app was reviewed by a native speaker, and line-by-line proofreading is still to do. Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Brandon Thomas
Claude Opus 5.5
parent
b4509d2368
commit
a0aa0863bf
@@ -69,3 +69,4 @@ Generated-in-code assets are original and have no file to list:
|
||||
| `crates/ui-egui/src/i18n/ko.tsv` | @huk082 (AI-assisted) | Original Korean translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied; no font assets added |
|
||||
| `crates/ui-egui/src/i18n/ar.tsv` | @hasan-sdaif | Original Arabic translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied |
|
||||
| `crates/ui-egui/src/i18n/hu.tsv` | @Skaywalker | Original Hungarian translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied |
|
||||
| `crates/ui-egui/src/i18n/tr.tsv` | @ogzhnklvz (AI-assisted) | Original Turkish translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied; written from the English strings, no other catalog used as a source; the running app reviewed by a native speaker |
|
||||
|
||||
@@ -111,7 +111,7 @@ numbers):
|
||||
| Layouts & plotting | Paper-space layouts, viewports (scale, lock, per-viewport layer freeze), MSPACE/PSPACE through viewports, page setups, PLOT and EXPORTPDF |
|
||||
| Parametric | Geometric and dimensional constraints, AUTOCONSTRAIN, PARAMETERS with expressions, conflict detection; constraints re-solve after every edit |
|
||||
| Grips | Hot grips with Space to cycle Stretch, Move, Rotate, Scale and Mirror |
|
||||
| Interface languages | English, Ukrainian (Українська), Brazilian Portuguese (Português (Brasil)), German (Deutsch), Spanish (Español), Czech (Čeština), Russian (Русский), French (Français), Simplified Chinese (简体中文, with an installed CJK font), Italian (Italiano), Korean (한국어, with an installed Hangul font), Swedish (Svenska), Arabic (العربية, with an installed Arabic font) and Hungarian (Magyar), live switching and a remembered Auto/system-language choice; [details](docs/localization.md) |
|
||||
| Interface languages | English, Ukrainian (Українська), Brazilian Portuguese (Português (Brasil)), German (Deutsch), Spanish (Español), Czech (Čeština), Russian (Русский), French (Français), Simplified Chinese (简体中文, with an installed CJK font), Italian (Italiano), Korean (한국어, with an installed Hangul font), Swedish (Svenska), Arabic (العربية, with an installed Arabic font), Hungarian (Magyar) and Turkish (Türkçe), live switching and a remembered Auto/system-language choice; [details](docs/localization.md) |
|
||||
| Automation | MCP server, JSON control channel, `cadcraft-cli` (info, convert, run, commands, mcp) |
|
||||
|
||||
## Quick start
|
||||
|
||||
@@ -41,10 +41,12 @@ pub enum Preference {
|
||||
Arabic,
|
||||
#[serde(rename = "hu")]
|
||||
Hungarian,
|
||||
#[serde(rename = "tr")]
|
||||
Turkish,
|
||||
}
|
||||
|
||||
impl Preference {
|
||||
pub const ALL: [Self; 15] = [
|
||||
pub const ALL: [Self; 16] = [
|
||||
Self::Auto,
|
||||
Self::English,
|
||||
Self::Ukrainian,
|
||||
@@ -60,6 +62,7 @@ impl Preference {
|
||||
Self::Swedish,
|
||||
Self::Arabic,
|
||||
Self::Hungarian,
|
||||
Self::Turkish,
|
||||
];
|
||||
|
||||
/// The codes a preference can be given as, for messages ("auto, en or uk").
|
||||
@@ -88,6 +91,7 @@ impl Preference {
|
||||
Self::Swedish => "sv",
|
||||
Self::Arabic => "ar",
|
||||
Self::Hungarian => "hu",
|
||||
Self::Turkish => "tr",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +118,7 @@ impl Preference {
|
||||
Self::Swedish => "Svenska",
|
||||
Self::Arabic => "العربية",
|
||||
Self::Hungarian => "Magyar",
|
||||
Self::Turkish => "Türkçe",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +147,7 @@ impl Preference {
|
||||
Self::Swedish => "sv",
|
||||
Self::Arabic => "ar",
|
||||
Self::Hungarian => "hu",
|
||||
Self::Turkish => "tr",
|
||||
Self::Auto => locales.iter().find_map(|s| locale_language(s)).unwrap_or("en"),
|
||||
}
|
||||
}
|
||||
@@ -158,7 +164,7 @@ pub struct Language {
|
||||
catalog: OnceLock<Catalog<'static>>,
|
||||
}
|
||||
|
||||
pub static LANGUAGES: [Language; 14] = [
|
||||
pub static LANGUAGES: [Language; 15] = [
|
||||
Language { code: "en", name: "English", source: "", plural: plural_en, plural_forms: 2, catalog: OnceLock::new() },
|
||||
Language {
|
||||
code: "uk", name: "Українська", source: include_str!("uk.tsv"), plural: plural_uk, plural_forms: 3, catalog: OnceLock::new()
|
||||
@@ -195,6 +201,8 @@ pub static LANGUAGES: [Language; 14] = [
|
||||
Language { code: "ar", name: "العربية", source: include_str!("ar.tsv"), plural: plural_arabic, plural_forms: 6, catalog: OnceLock::new() },
|
||||
// Hungarian uses the singular after a numeral, so one form covers every count (the Korean rule).
|
||||
Language { code: "hu", name: "Magyar", source: include_str!("hu.tsv"), plural: plural_ko, plural_forms: 1, catalog: OnceLock::new() },
|
||||
// Turkish keeps a noun singular after a number ("3 commit"), so like Korean it has one form.
|
||||
Language { code: "tr", name: "Türkçe", source: include_str!("tr.tsv"), plural: plural_ko, plural_forms: 1, catalog: OnceLock::new() },
|
||||
];
|
||||
|
||||
/// BCP 47 and POSIX locale tags, including `uk-UA`, `uk_UA.UTF-8` and `pt_BR.UTF-8`.
|
||||
|
||||
@@ -39,7 +39,7 @@ fn catalog_is_valid_and_preserves_placeholders_and_ellipses() {
|
||||
/// to English for what they don't cover yet; their gaps are reported, not enforced, so adding a
|
||||
/// command doesn't require a row in every language.
|
||||
const REQUIRED: &[&str] = &["uk"];
|
||||
const REPORTED: &[&str] = &["pt-BR", "de", "es", "cs", "ru", "fr", "zh", "it", "ko", "sv", "ar", "hu"];
|
||||
const REPORTED: &[&str] = &["pt-BR", "de", "es", "cs", "ru", "fr", "zh", "it", "ko", "sv", "ar", "hu", "tr"];
|
||||
|
||||
fn check(language: &str, what: &str, missing: Vec<String>) {
|
||||
if REQUIRED.contains(&language) {
|
||||
@@ -1021,3 +1021,111 @@ fn default_fonts_cover_hungarian_letters_and_quotes() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn turkish_locales_preferences_and_single_count_form() {
|
||||
for tag in ["tr", "tr-TR", "tr_TR.UTF-8", "TR-tr", " tr-TR ", "tr-CY"] {
|
||||
assert_eq!(locale_language(tag), Some("tr"), "{tag}");
|
||||
}
|
||||
for tag in ["tur", "türkçe"] {
|
||||
assert_eq!(locale_language(tag), None, "{tag}");
|
||||
}
|
||||
assert_eq!(Preference::parse("tr"), Some(Preference::Turkish));
|
||||
assert_eq!(Preference::Turkish.name(), "Türkçe");
|
||||
assert_eq!(Preference::Turkish.resolve(&["en-US".into()]), "tr");
|
||||
assert_eq!(Preference::Auto.resolve(&["pl-PL".into(), "tr-TR".into(), "en-US".into()]), "tr");
|
||||
let mut app = CadApp::new(Session::new(), Services::default());
|
||||
app.ui.interface_language = Preference::Turkish;
|
||||
let mut restored = CadApp::new(Session::new(), Services::default());
|
||||
restored.load_prefs(&app.prefs_json());
|
||||
assert_eq!(restored.ui.interface_language, Preference::Turkish);
|
||||
with_language("tr", || {
|
||||
// A Turkish noun stays singular after a number, 1 included.
|
||||
for n in [0, 1, 2, 5, 21, u64::MAX] {
|
||||
assert_eq!(count(n, "{n} contributor", "{n} contributors"), format!("{n} katkıda bulunan"));
|
||||
assert_eq!(count(n, "{n} commit", "{n} commits"), format!("{n} commit"));
|
||||
}
|
||||
assert_eq!(format("Current: {color}", &[("color", "{n} Open".into())]), "Geçerli: {n} Open");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn turkish_menu_headings_keep_object_labels_and_prompt_keywords() {
|
||||
with_language("tr", || {
|
||||
assert_eq!(menu("Dimension"), "Ölçülendirme");
|
||||
assert_eq!(t("Dimension"), "Ölçü");
|
||||
assert_eq!(menu("View"), "Görünüm");
|
||||
assert_eq!(menu("Draw"), "Çiz");
|
||||
assert_eq!(menu("Modify"), "Değiştir");
|
||||
assert_eq!(menu("Edit"), "Düzenle");
|
||||
assert_eq!(menu("File"), "Dosya");
|
||||
// Clickable keywords keep the spelling the engine accepts.
|
||||
assert_eq!(t("Enter Top, Zero or Bottom."), "Top, Zero veya Bottom girin.");
|
||||
assert_eq!(t("Specify first point on circle: _tan to"), "Daire üzerindeki ilk noktayı belirtin: _tan to");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn live_turkish_switch_preserves_drawing_command_and_saved_choice() {
|
||||
let mut app = CadApp::new(Session::new(), Services::default());
|
||||
app.ui.in_window_menu = true;
|
||||
app.session.state_mut().unwrap().title = "Open".into();
|
||||
let ctx = egui::Context::default();
|
||||
app.logic(&ctx);
|
||||
assert!(render(&mut app, &ctx).contains("Properties"));
|
||||
app.start("line");
|
||||
let prompt = crate::control::cmdline_state(&app);
|
||||
let commands = crate::control::all_commands(&app);
|
||||
app.run("ui.language", json!({"lang":"tr"})).unwrap();
|
||||
let text = render(&mut app, &ctx);
|
||||
for label in ["Özellikler", "Dosya", "Görünüm", "Çiz", "Ölçülendirme", "İlk noktayı belirtin"] {
|
||||
assert!(text.contains(label), "missing {label}: {text}");
|
||||
}
|
||||
assert_eq!(app.language(), "tr");
|
||||
assert_eq!(app.session.state().unwrap().title, "Open");
|
||||
assert_eq!(crate::control::cmdline_state(&app), prompt);
|
||||
assert_eq!(crate::control::all_commands(&app), commands);
|
||||
app.run("ui.language", json!({"lang":"en"})).unwrap();
|
||||
assert!(render(&mut app, &ctx).contains("Properties"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn turkish_dialogs_render_with_stable_ids() {
|
||||
for (dialog, heading) in [
|
||||
("dsettings", "Çizim Ayarları"),
|
||||
("about", "CADCraft Hakkında"),
|
||||
("blocks", "Bloklar"),
|
||||
("layers", "Katman Özellikleri Yöneticisi"),
|
||||
("qselect", "Hızlı Seçim"),
|
||||
("parameters", "Parametre Yöneticisi"),
|
||||
("language", "Türkçe"),
|
||||
("options:preferences", "Kullanıcı Tercihleri"),
|
||||
] {
|
||||
let mut app = CadApp::new(Session::new(), Services::default());
|
||||
app.ui.interface_language = Preference::Turkish;
|
||||
app.ui.dialog = Some(dialog.into());
|
||||
let ctx = egui::Context::default();
|
||||
app.logic(&ctx);
|
||||
let text = render(&mut app, &ctx);
|
||||
assert!(text.contains(heading), "{dialog}: {text}");
|
||||
assert_eq!(app.ui.dialog.as_deref(), Some(dialog));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_fonts_cover_every_turkish_letter_in_the_catalog() {
|
||||
let ctx = egui::Context::default();
|
||||
let mut output = ctx.run_ui(Default::default(), |_| {});
|
||||
output.textures_delta.clear();
|
||||
let mut letters: BTreeSet<_> = "ÇĞİÖŞÜçğıöşü".chars().collect();
|
||||
let translations = include_str!("tr.tsv").lines().filter(|l| !l.starts_with('#')).filter_map(|l| l.rsplit('\t').next());
|
||||
letters.extend(translations.flat_map(str::chars).filter(|c| !c.is_ascii() && c.is_alphabetic()));
|
||||
ctx.fonts_mut(|view| {
|
||||
for family in [egui::FontFamily::Proportional, egui::FontFamily::Monospace] {
|
||||
let mut font = view.fonts.font(&family);
|
||||
for c in &letters {
|
||||
assert!(font.characters().contains_key(c), "missing {c} in {family:?}");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@
|
||||
//! |---|---|
|
||||
//! | `theme` | `"system"`, `"light"` or `"dark"` |
|
||||
//! | `animations` | `"system"`, `"on"` or `"off"`: dialog and menu fades and smoothed scrolling |
|
||||
//! | `interfaceLanguage` | `"auto"`, `"en"`, `"uk"`, `"pt-BR"`, `"de"`, `"es"`, `"cs"`, `"ru"`, `"fr"`, `"zh"`, `"it"`, `"ko"`, `"sv"`, `"ar"` or `"hu"` |
|
||||
//! | `interfaceLanguage` | `"auto"`, `"en"`, `"uk"`, `"pt-BR"`, `"de"`, `"es"`, `"cs"`, `"ru"`, `"fr"`, `"zh"`, `"it"`, `"ko"`, `"sv"`, `"ar"`, `"hu"` or `"tr"` |
|
||||
//! | `saveFormat` | `"dxf"` or `"dwg"`: the format Save As suggests for new drawings |
|
||||
//! | `saveVersion` | `"2000"` … `"2018"`: the version drawings with no file yet are saved in |
|
||||
//! | `SAVETIME` | minutes between automatic saves, 0–600 (0: off) |
|
||||
|
||||
@@ -69,8 +69,9 @@ plus native review by a human; extending the catalog to the remaining English-on
|
||||
| Swedish | sv | 1,330 catalog rows; reference catalog, marked UI literals and menu headings covered (no gaps reported) | dialogs and tooltips yes; contextual menu headings; command reference searchable in Swedish | Latin: yes (bundled egui proportional and monospace fonts; å ä ö é and Swedish quotes tested) | AI-assisted (Claude Code) by @holmbom; terminology and the running app reviewed by a native speaker | complete current catalog; English-only interface gaps remain | line-by-line proofreading + shared English-only UI work |
|
||||
| Italian | it | 1,227 catalog rows; reference catalog and marked UI literals covered | dialogs and tooltips yes; contextual menu headings (Visualizza / Vista, Edita / Modifica); command reference searchable in Italian | Latin: yes (bundled egui fonts; accented letters tested) | AI-assisted by Emanuele Bottelli (Claude), written from the English strings with Italian desktop-CAD vocabulary; no native proofreading pass yet | complete current catalog; English-only interface gaps remain | native review + shared English-only UI work |
|
||||
| Hungarian | hu | 1,326 catalog rows; reference catalog, marked UI literals and menu headings covered (no gaps reported) | dialogs and tooltips yes; contextual menu headings; command reference searchable in Hungarian | Latin: yes (bundled egui proportional and monospace fonts; ő ű Ő Ű and the other accented letters tested) | translated by @Skaywalker from the English strings; independent native proofreading pending | complete current catalog; English-only interface gaps remain | native proofreading + shared English-only UI work |
|
||||
| Turkish | tr | 1,330 catalog rows; reference catalog, marked UI literals and menu headings covered (no gaps reported) | dialogs and tooltips yes; contextual menu headings (Ölçülendirme / Ölçü); command reference searchable in Turkish | Latin: yes (bundled egui proportional and monospace fonts; Ç Ğ İ Ö Ş Ü ç ğ ı ö ş ü tested) | AI-assisted by @ogzhnklvz, written from the English strings with Turkish desktop-CAD vocabulary; the running app reviewed by a native speaker | complete current catalog; English-only interface gaps remain | line-by-line proofreading + shared English-only UI work |
|
||||
|
||||
Other languages shipped: Ukrainian, Brazilian Portuguese, German, Czech, Russian, French, Italian, Korean, Swedish and Hungarian.
|
||||
Other languages shipped: Ukrainian, Brazilian Portuguese, German, Czech, Russian, French, Italian, Korean, Swedish, Hungarian and Turkish.
|
||||
Czech, Swedish, Hungarian and Brazilian Portuguese cover the reference catalog and every marked UI literal; engine diagnostics and uncatalogued text
|
||||
remain English. AutoCAD for Mac ships 7
|
||||
non-English languages (zh-Hans, es, fr, ja, de, ko, it); of those, CADCraft now ships German and Korean,
|
||||
@@ -85,6 +86,7 @@ each language, which needs humans. Translations parallelise fully once the catal
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-14 | minor | Swedish completed: 95 rows for strings added since (Hatch and Gradient dialog, Block Editor, REFEDIT, multileader editing, Options selection settings, MTEXT editor, recent files); 1,330 rows, every key of the Ukrainian reference catalog |
|
||||
| 2026-10-18 | minor | Turkish added: 1,330 rows (the existing catalog union), single count form, four menu headings, prompt keywords kept in English; locale/preferences/menu/live-switch/dialog/font tests; no gaps in the marked UI literals; AI-assisted, the running app reviewed by a native speaker |
|
||||
| 2026-10-13 | minor | Hungarian added: 1,326 rows, a single count form, menu headings, locale/preferences/menu/font/render tests; no gaps in the marked UI literals; native proofreading pending |
|
||||
| 2026-10-13 | minor | Swedish added: 1,235 rows, one/other plurals, menu headings, locale/preferences/menu/font/render tests; no gaps in the marked UI literals; terminology and the running app reviewed by a native speaker |
|
||||
| 2026-10-13 | minor | Korean added: full 1,235-row existing catalog union, single count form, locale/persistence/live-switch tests, and validated Hangul UI fonts; native review and platform verification pending |
|
||||
|
||||
+14
-3
@@ -1,7 +1,7 @@
|
||||
# Interface languages
|
||||
|
||||
Choose **Edit → Interface Language** and select **Auto (system language)**, **English**,
|
||||
**Українська**, **Português (Brasil)**, **Deutsch**, **Español**, **Čeština** (Czech), **Русский**, **Français**, **简体中文**, **Italiano**, **한국어** (Korean), **Svenska** (Swedish), **العربية** (Arabic), or **Magyar** (Hungarian).
|
||||
**Українська**, **Português (Brasil)**, **Deutsch**, **Español**, **Čeština** (Czech), **Русский**, **Français**, **简体中文**, **Italiano**, **한국어** (Korean), **Svenska** (Swedish), **العربية** (Arabic), **Magyar** (Hungarian), or **Türkçe** (Turkish).
|
||||
The interface updates without restarting, including the native macOS menus.
|
||||
The choice is saved with the other interface preferences (`cadcraft.prefs`, beside the theme):
|
||||
eframe storage on the desktop, browser local storage on the web. Installations without a saved
|
||||
@@ -11,7 +11,7 @@ Auto uses the first supported language in the operating system's preferred local
|
||||
browser's `navigator.languages` on the web. BCP 47 and POSIX tags select their primary language:
|
||||
`uk-UA` → `uk`, `de_AT.UTF-8` → `de`, `es-MX` → `es`, `pt_BR.UTF-8` → `pt-BR`,
|
||||
`cs-CZ` and `cs_CZ.UTF-8` → `cs`, `it-IT` and `it_CH.UTF-8` → `it`, `ko-KR` and `ko_KR.UTF-8` → `ko`,
|
||||
`sv-SE`, `sv-FI` and `sv_SE.UTF-8` → `sv`, `hu-HU` and `hu_HU.UTF-8` → `hu`. Unsupported languages fall back to English.
|
||||
`sv-SE`, `sv-FI` and `sv_SE.UTF-8` → `sv`, `hu-HU` and `hu_HU.UTF-8` → `hu`, `tr-TR` and `tr_TR.UTF-8` → `tr`. Unsupported languages fall back to English.
|
||||
Set `CADCRAFT_LOCALE=cs-CZ` to override the desktop's locale for a launch.
|
||||
An explicit saved language choice takes precedence over that override.
|
||||
|
||||
@@ -22,7 +22,7 @@ Automation can select the language through the existing control channel:
|
||||
```
|
||||
|
||||
The `ui.set` method also accepts `{"interfaceLanguage":"cs"}`. Supported values are `auto`,
|
||||
`en`, `uk`, `pt-BR`, `de`, `es`, `cs`, `ru`, `fr`, `zh`, `it`, `ko`, `sv`, `ar`, and `hu`; invalid values are rejected without changing the current
|
||||
`en`, `uk`, `pt-BR`, `de`, `es`, `cs`, `ru`, `fr`, `zh`, `it`, `ko`, `sv`, `ar`, `hu`, and `tr`; invalid values are rejected without changing the current
|
||||
selection. Resetting palettes keeps the language choice.
|
||||
|
||||
## Translation coverage
|
||||
@@ -61,6 +61,17 @@ a count takes one form because a Hungarian numeral is followed by the singular.
|
||||
was written from the meaning of CADCraft's English strings; no other product's localization was
|
||||
used as a source. It has not yet been proofread by an independent native speaker.
|
||||
|
||||
Turkish has **1,330 rows**: the union of the existing catalogs, four contextual menu headings
|
||||
(**Ölçülendirme** for the Dimension menu, **Ölçü** for the object) and two single-form count
|
||||
templates, since a Turkish noun stays singular after a number ("3 commit"). No marked UI literal
|
||||
falls back to English. Prompts read "… girin" for Enter and "… belirtin" for Specify, and clickable
|
||||
keywords (`Top`, `Zero`, `Bottom`, `_tan to`, `nX`/`nXP`) keep the spelling the engine accepts.
|
||||
The translation is original, AI-assisted work by @ogzhnklvz, written from the English strings with
|
||||
Turkish desktop-CAD vocabulary (Katman, Tarama, Yuvarlatma, Pah, Öteleme, Nesne Kenetleme,
|
||||
Görünüm Penceresi); the running app was reviewed by a native speaker, and line-by-line
|
||||
proofreading is still to do. The bundled
|
||||
egui fonts cover `Ç Ğ İ Ö Ş Ü ç ğ ı ö ş ü`.
|
||||
|
||||
Drawing titles, layer/layout/block/style names, parameter names and expressions, text in a
|
||||
drawing, and command-line input are user data and retain their original spelling. Clickable
|
||||
command keywords retain their English spelling so the text shown matches the input accepted
|
||||
|
||||
Reference in New Issue
Block a user