Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/frontend
diff options
context:
space:
mode:
authorLeitwolf112026-10-03 13:38:38 +0300
committerLeitwolf112026-10-03 13:38:38 +0300
commited7f6e57d50765728e7d0513aaf956ec667ddc98 (patch)
tree2a3500198ec6e5a18699eac9e84b2484a8e51cc0 /frontend
parent3173a6a2bfe1975542c8c9cc0707071daa55b587 (diff)
downloadwebsite-ed7f6e57d50765728e7d0513aaf956ec667ddc98.tar.gz
Revise the Hebrew wording and remember only a visitor's language choice
Hebrew A second pass over the Hebrew text replaced words a Hebrew reader would misread or that are not used for the concept: "native" was rendered with the word for "local", "lowering" with the word for "download", "pipeline" with a literal pipe and "front end" with a word not used for compilers. Typed forms, diagnostics, the ecosystem and the standard library use the usual terms. The text is still not reviewed by a native speaker. Language choice A language change is now stored only after the visitor has acted on the page, as reported by navigator.userActivation. A change that reaches the page before anyone has clicked, tapped or typed still changes the language but is not remembered, so only a person can make a choice. A browser without the activation API keeps the earlier behaviour. During local testing a choice was once found stored without one being made. It could not be reproduced in three attempts, and restoring form state was shown not to fire a change event, so the cause is unknown; this guard closes the path in the page itself. Verified locally: frontend tests, type check, prettier and build. In a browser, a scripted change before any interaction switched the language and stored nothing, and a change after a real click was stored and survived a navigation. The forum page was opened in a browser: one notice, no language menu, English for a Turkish browser, and the Hebrew, German and Russian notices when the script ran with those browser languages.
Diffstat (limited to 'frontend')
-rw-r--r--frontend/src/locales.ts13
-rw-r--r--frontend/src/pages/GettingStartedPage.vue8
-rw-r--r--frontend/src/pages/HomePage.vue6
-rw-r--r--frontend/src/pages/OverviewPage.vue26
-rw-r--r--frontend/src/preferences.ts15
-rw-r--r--frontend/src/seo.ts2
-rw-r--r--frontend/tests/locales.test.mjs8
-rw-r--r--frontend/tests/seo.test.mjs2
8 files changed, 55 insertions, 25 deletions
diff --git a/frontend/src/locales.ts b/frontend/src/locales.ts
index 34e2bba..4d99d09 100644
--- a/frontend/src/locales.ts
+++ b/frontend/src/locales.ts
@@ -53,6 +53,19 @@ export function initialLocale(chosen: string | null, languages: readonly string[
}
/**
+ * Whether a language change may be remembered as the visitor's choice.
+ *
+ * A choice needs a visitor: a change that reaches the page before anyone has
+ * clicked, tapped or typed in it did not come from the language menu, so it
+ * changes the page but is not stored. The argument is the browser's
+ * `navigator.userActivation`; a browser without it cannot tell, and there a
+ * change counts as a choice.
+ */
+export function isVisitorChoice(activation: { hasBeenActive: boolean } | undefined): boolean {
+ return activation?.hasBeenActive ?? true;
+}
+
+/**
* The direction in which the text of a language runs.
*
* Only text follows it. The page layout, the navigation and code samples keep
diff --git a/frontend/src/pages/GettingStartedPage.vue b/frontend/src/pages/GettingStartedPage.vue
index e6bfd82..ecde15f 100644
--- a/frontend/src/pages/GettingStartedPage.vue
+++ b/frontend/src/pages/GettingStartedPage.vue
@@ -195,7 +195,7 @@ const text = {
"שכפלו את מאגר המהדר יחד עם תת־המודולים שלו. השתמשו במחשב פיתוח נתמך עם Windows 10/11 או עם גרסה עדכנית של macOS.",
step2: "2. בדיקת שרשרת הכלים",
step2Text:
- "פקודת הפיתוח של המאגר, הכתובה ב-Go, בודקת את הדרישות המקומיות. המהדר משתמש ב-GHC2024 לחזית הכתובה ב-Haskell, ב-Clang/LLVM לשלבים המקומיים ב-C++20, ב-Bazel לבניות המקומיות וב-Temurin JDK 25 ל-DSL של הפרויקטים.",
+ "פקודת הפיתוח של המאגר, הכתובה ב-Go, בודקת את הדרישות המקומיות. המהדר משתמש ב-GHC2024 ל-frontend הכתוב ב-Haskell, ב-Clang/LLVM לשלבי ה-native ב-C++20, ב-Bazel לבניית חלקי ה-native וב-Temurin JDK 25 ל-DSL של הפרויקטים.",
platform:
"מחשבי הפיתוח הנתמכים הם Windows 10/11 ו-macOS Sequoia/Tahoe. ב-Windows נעשה שימוש ב-clang-cl וב-LLD עצמאיים של LLVM יחד עם Windows SDK וספריות ה-CRT/STL של MSVC. ב-macOS יש להתקין את Xcode Command Line Tools; יישום Xcode המלא אינו נדרש.",
toolchainHelp:
@@ -203,12 +203,12 @@ const text = {
bootstrap: "הכנת מחשב אופציונלית",
step3: "3. בנייה ובדיקה",
step3Text:
- "בנו את המהדר המקומי והריצו את חבילות בדיקות החוזה המקומיות שלו. פקודת ה-Go מתזמרת את הבדיקות; Bazel נשאר הבעלים של גרף הבנייה של C++20. Cabal ו-Gradle מטפלים בגבולות של Haskell ושל Kotlin.",
+ "בנו את מהדר ה-native והריצו את חבילות בדיקות החוזה שלו. פקודת ה-Go מתזמרת את הבדיקות; Bazel נשאר הבעלים של גרף הבנייה של C++20. Cabal ו-Gradle מטפלים בגבולות של Haskell ושל Kotlin.",
step4: "4. קריאה ובדיקה של תוכנית אמיתית",
step4Text:
"בדוגמה HelloWorld נקודת הכניסה היא מתודה של מחלקה. Visual X#‎ אינה משתמשת בפונקציה ברמה העליונה כנקודת הכניסה לתוכנית. בדקו את קובץ המקור המדויק, ואז בנו אותו בתת־הקבוצה הנוכחית של המהדר.",
fileCheck: "בדיקת קובץ מקור יחיד",
- fileBuild: "בניית קובץ הרצה מקומי",
+ fileBuild: "בניית קובץ הרצה בקוד מכונה",
subset:
"תת־הקבוצה של קוד המקור שמתקבלת צרה מהמפרט הציבורי המלא. בנייה מוצלחת היא ראיה חזקה יותר לתוכנית מסוימת מאשר דוגמת תחביר במפרט; הרצת בדיקות מוצלחת היא ראיה חזקה יותר למשפחת יכולות.",
step5: "5. לעקוב אחר החוזה הציבורי",
@@ -222,7 +222,7 @@ const text = {
},
{
title: "מדריך בנייה",
- detail: "מחשבים רשמיים, איתור שרשרת הכלים ויעדי בנייה מקומיים.",
+ detail: "מחשבים רשמיים, איתור שרשרת הכלים ויעדי הבנייה של חלקי ה-native.",
href: "https://github.com/Progmasoft/visual-xsharp/blob/main/Documents/BUILDING.md",
},
{
diff --git a/frontend/src/pages/HomePage.vue b/frontend/src/pages/HomePage.vue
index fbdff2f..f432632 100644
--- a/frontend/src/pages/HomePage.vue
+++ b/frontend/src/pages/HomePage.vue
@@ -197,7 +197,7 @@ const translations = {
eyebrow: "שפה לבנייה מתוך בהירות",
title: "להפוך את התוכנית כולה למובנת.",
intro:
- "Visual X#‎ שואפת לשלב קוד מקור רב־הבעה עם בעלות מפורשת, צינור מהדר גלוי ופלט מקומי. היא נבנית בפתיחות: המפרט מתאר את השפה המיועדת, וכיסוי המימוש עדיין הולך וגדל.",
+ "Visual X#‎ שואפת לשלב קוד מקור אקספרסיבי עם בעלות מפורשת, תהליך הידור גלוי ופלט בקוד מכונה. היא נבנית בפתיחות: המפרט מתאר את השפה המיועדת, וכיסוי המימוש עדיין הולך וגדל.",
start: "להתחיל לקרוא",
overview: "למה Visual X#‎?",
github: "למעקב אחר הפיתוח",
@@ -218,7 +218,7 @@ const translations = {
{
number: "03",
title: "מהדר שאפשר לבחון",
- text: "לניתוח התחבירי, לפענוח השמות, לבדיקת הטיפוסים, ל-Core, ל-Xpp ול-Xmm יש תחומי אחריות נפרדים. הדרך אל LLVM ואל קובץ הרצה מקומי גלויה ואינה קופסה שחורה.",
+ text: "לניתוח התחבירי, לפענוח השמות, לבדיקת הטיפוסים, ל-Core, ל-Xpp ול-Xmm יש תחומי אחריות נפרדים. הדרך אל LLVM ואל קובץ הרצה בקוד מכונה גלויה ואינה קופסה שחורה.",
},
],
codeTitle: "נקודת התחלה מוכרת",
@@ -242,7 +242,7 @@ const translations = {
},
{
title: "לעקוב אחר העבודה",
- body: "המאגר מכיל את השפה, את שלבי המהדר המקומיים, את כלי הפרויקט, דוגמאות ומסמכי פיתוח. האתר הזה הוא מדריך אל העבודה הזאת, לא הצהרה על שרשרת כלים מוגמרת.",
+ body: "המאגר מכיל את השפה, את שלבי ה-native של המהדר, את כלי הפרויקט, דוגמאות ומסמכי פיתוח. האתר הזה הוא מדריך אל העבודה הזאת, לא הצהרה על שרשרת כלים מוגמרת.",
link: "למאגר",
href: "https://github.com/Progmasoft/visual-xsharp",
},
diff --git a/frontend/src/pages/OverviewPage.vue b/frontend/src/pages/OverviewPage.vue
index d259789..af40b98 100644
--- a/frontend/src/pages/OverviewPage.vue
+++ b/frontend/src/pages/OverviewPage.vue
@@ -357,7 +357,7 @@ const text = {
navStart: "צעדים ראשונים",
section: "תיעוד / סקירה",
title: "מה Visual X#‎ מנסה לפתור",
- lead: "Visual X#‎ מתוכננת סביב שאלה פשוטה: האם קוד רב־הבעה יכול להישאר מובן כאשר בעלות, טיפוסים והידור מקומי חשובים? העמוד הזה מסביר את הכיוון, ואינו הבטחה שכל יכולת כבר מוגמרת.",
+ lead: "Visual X#‎ מתוכננת סביב שאלה פשוטה: האם קוד אקספרסיבי יכול להישאר מובן כאשר בעלות, טיפוסים והידור לקוד מכונה חשובים? העמוד הזה מסביר את הכיוון, ואינו הבטחה שכל יכולת כבר מוגמרת.",
goals: "יעדי התכנון",
modelHeading: "כמה בחירות של השפה",
modelIntro:
@@ -372,12 +372,12 @@ const text = {
body: "טיפוס ערך נשאר טיפוס ערך רק כאשר כל ארגומנט גנרי מקונן הוא טיפוס ערך. טיפוס הפניה בכל מקום במבנה הגנרי הופך את התוצאה לטיפוס הפניה.",
},
{
- title: "משטח אחד של ספרייה סטנדרטית",
+ title: "ספרייה סטנדרטית אחת",
body: "מרחבי השמות של System מחזיקים את היכולות הבסיסיות, כגון קלט ופלט במסוף, מערכים, טקסט ומתמטיקה. מרחב שמות של הספרייה הסטנדרטית אינו תלות חבילה שמצהירים עליה בנפרד.",
},
{
- title: "פלט מקומי, בלי להעמיד פנים שהצינור מוגמר",
- body: "למהדר יש נתיב מקוד מקור לקוד מקומי עבור תת־הקבוצה שמומשה. היעד הוא כיסוי סמנטי רחב יותר, גבולות ביניים מאומתים ואבחונים אמינים ככל שהשפה גדלה.",
+ title: "פלט בקוד מכונה, בלי להעמיד פנים שהתהליך מוגמר",
+ body: "למהדר יש נתיב מקוד מקור לקוד מכונה עבור תת־הקבוצה שמומשה. היעד הוא כיסוי סמנטי רחב יותר, גבולות ביניים מאומתים והודעות אבחון אמינות ככל שהשפה גדלה.",
},
],
pipelineHeading: "למהדר יש גבולות גלויים",
@@ -386,23 +386,23 @@ const text = {
pipeline: [
{
title: "קוד מקור ותחביר",
- body: "המנתח הלקסיקלי והמנתח התחבירי, הכתובים ב-Haskell, מפיקים AST מנותח ושומרים את מיקומי המקור לצורך אבחונים.",
+ body: "המנתח הלקסיקלי והמנתח התחבירי, הכתובים ב-Haskell, מפיקים AST מנותח ושומרים את מיקומי המקור לצורך הודעות אבחון.",
},
{
title: "שמות וטיפוסים",
- body: "שינוי שמות, פענוח שמות ובדיקת טיפוסים מפיקים צורות AST נפרדות: מפוענחת ומוגדרת טיפוסים.",
+ body: "שינוי שמות, פענוח שמות ובדיקת טיפוסים מפיקים צורות AST נפרדות: מפוענחת ובעלת טיפוסים.",
},
{
title: "סמנטיקת השפה",
body: "פירוק הסוכר התחבירי והאופטימיזציות של Core פועלים לפני המתאם הפרטי CorePrep.",
},
{
- title: "התאמה מקומית",
+ title: "התאמה לקוד מכונה",
body: "השלבים Xpp ו-Xmm, הכתובים ב-C++20, נושאים ייצוג מאומת ובלתי תלוי ביעד לקראת LLVM.",
},
{
title: "קובץ הרצה",
- body: "LLVM מוריד את התוכנית המאומתת לקוד אובייקט, ולאחר מכן שלב קישור של הפלטפורמה יוצר תוצר ‎.vxse.",
+ body: "LLVM מתרגם את התוכנית המאומתת לקוד אובייקט, ולאחר מכן שלב קישור של הפלטפורמה יוצר תוצר ‎.vxse.",
},
],
boundariesHeading: "היכן עוברים הגבולות היום",
@@ -413,7 +413,7 @@ const text = {
},
{
label: "האמת של המימוש",
- value: "בדיקות המהדר, תת־הקבוצה הנתמכת ואבחונים מפורשים",
+ value: "בדיקות המהדר, תת־הקבוצה הנתמכת והודעות אבחון מפורשות",
},
{
label: "הגדרת הפרויקט",
@@ -446,15 +446,15 @@ const text = {
items: [
{
title: "סמנטיקה לפני קיצורי דרך",
- body: "לשפת המקור יש מפרט כתוב. המהדר מפריד בין תחביר מנותח, מפוענח ומוגדר טיפוסים, כך שהמעברים המאוחרים מקבלים משמעות מפורשת במקום לנחש.",
+ body: "לשפת המקור יש מפרט כתוב. המהדר מפריד בין תחביר מנותח, מפוענח ובעל טיפוסים, כך שהמעברים המאוחרים מקבלים משמעות מפורשת במקום לנחש.",
},
{
title: "בעלות שאפשר לעקוב אחריה",
- body: "ההתנהגות של הפניות ושל ערכים מוגדרת דרך הרכב הטיפוסים. ספירת הפניות אוטומטית וכללי העתקה־בעת־כתיבה הם חלק ממודל השפה; התמיכה בזמן ריצה ובהורדה עדיין בהשלמה.",
+ body: "ההתנהגות של הפניות ושל ערכים מוגדרת דרך הרכב הטיפוסים. ספירת הפניות אוטומטית וכללי העתקה־בעת־כתיבה הם חלק ממודל השפה; התמיכה בזמן ריצה ובתרגום לשלבים הנמוכים עדיין בהשלמה.",
},
{
- title: "צינור מקומי מכוון",
- body: "החזית מורידה את התוכנית דרך Core ו-CorePrep, ולאחר מכן Xpp ו-Xmm מתאימים אותה ליצירת הקוד של LLVM. הגבולות מאפשרים אימות ואבחונים בכל שלב.",
+ title: "תהליך הידור מכוון לקוד מכונה",
+ body: "ה-frontend מתרגם את התוכנית דרך Core ו-CorePrep, ולאחר מכן Xpp ו-Xmm מתאימים אותה ליצירת הקוד של LLVM. הגבולות מאפשרים אימות והודעות אבחון בכל שלב.",
},
],
not: "מה היא איננה",
diff --git a/frontend/src/preferences.ts b/frontend/src/preferences.ts
index 18d6615..a809bab 100644
--- a/frontend/src/preferences.ts
+++ b/frontend/src/preferences.ts
@@ -2,7 +2,13 @@
// SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1
import { computed, ref, watch } from "vue";
-import { forwardArrow, initialLocale, textDirection, type Locale } from "./locales";
+import {
+ forwardArrow,
+ initialLocale,
+ isVisitorChoice,
+ textDirection,
+ type Locale,
+} from "./locales";
export { supportedLocales, type Locale } from "./locales";
export type Theme = "dark" | "light";
@@ -30,10 +36,13 @@ function showLocale(value: Locale): void {
}
showLocale(locale.value);
-// The language changes only through the menu, so a change is a choice.
+// The language changes through the menu. It is remembered only when a
+// visitor has acted on the page, so nothing but a person makes a choice.
watch(locale, (value) => {
showLocale(value);
- localStorage.setItem(localeChoiceKey, value);
+ if (isVisitorChoice(navigator.userActivation)) {
+ localStorage.setItem(localeChoiceKey, value);
+ }
});
watch(
diff --git a/frontend/src/seo.ts b/frontend/src/seo.ts
index c4e5e82..0df93f0 100644
--- a/frontend/src/seo.ts
+++ b/frontend/src/seo.ts
@@ -66,7 +66,7 @@ const metadata: Record<Locale, Record<PublicRoute, PageMetadata>> = {
"/": {
title: "Visual X#‎ — להפוך את התוכנית כולה למובנת",
description:
- "הכירו את Visual X#‎: שפת תכנות מקומית הבנויה סביב קוד מקור קריא, בעלות מפורשת וצינור מהדר שאפשר לבחון.",
+ "הכירו את Visual X#‎: שפת תכנות שמהודרת לקוד מכונה והבנויה סביב קוד מקור קריא, בעלות מפורשת ותהליך הידור שאפשר לבחון.",
},
"/docs/overview": {
title: "סקירה · Visual X#‎",
diff --git a/frontend/tests/locales.test.mjs b/frontend/tests/locales.test.mjs
index 64509a5..0b87174 100644
--- a/frontend/tests/locales.test.mjs
+++ b/frontend/tests/locales.test.mjs
@@ -9,6 +9,7 @@ import {
forwardArrow,
initialLocale,
isLocale,
+ isVisitorChoice,
localeLabels,
supportedLocales,
textDirection,
@@ -64,3 +65,10 @@ test("only Hebrew text runs right to left", () => {
assert.equal(forwardArrow(locale), expected === "rtl" ? "←" : "→", locale);
}
});
+
+test("a language change is remembered only after the visitor acted on the page", () => {
+ assert.equal(isVisitorChoice({ hasBeenActive: true }), true);
+ assert.equal(isVisitorChoice({ hasBeenActive: false }), false);
+ // A browser that does not report activation cannot tell; the change counts.
+ assert.equal(isVisitorChoice(undefined), true);
+});
diff --git a/frontend/tests/seo.test.mjs b/frontend/tests/seo.test.mjs
index 7104f5c..82de8f9 100644
--- a/frontend/tests/seo.test.mjs
+++ b/frontend/tests/seo.test.mjs
@@ -96,7 +96,7 @@ test("the Hebrew routes have their own titles and keep the canonical URLs", () =
const { document, elements } = fakeDocument();
applyPageMetadata("/", "he-IL");
assert.match(document.title, /^Visual X#‎ — להפוך את התוכנית כולה למובנת$/);
- assert.match(elements.get('meta[name="description"]').content, /שפת תכנות מקומית/);
+ assert.match(elements.get('meta[name="description"]').content, /שמהודרת לקוד מכונה/);
assert.equal(elements.get('link[rel="canonical"]').href, "https://xsharp-lang.xyz/");
applyPageMetadata("/docs/overview", "he-IL");
assert.equal(document.title, "סקירה · Visual X#‎");