From d0fd45ba2dfdc8fbcc69316d85a0b307c134008c Mon Sep 17 00:00:00 2001 From: Grace Date: Wed, 11 Jun 2025 17:06:42 +0100 Subject: [PATCH 01/10] Update language dialog to include MakeCode - Add flag for translationPreview for previewing CreateAI UI translations --- lang/ui.ca.json | 16 +++ lang/ui.en.json | 16 +++ lang/ui.es-es.json | 16 +++ lang/ui.ja.json | 16 +++ lang/ui.ko.json | 16 +++ lang/ui.nl.json | 16 +++ lang/ui.pl.json | 16 +++ lang/ui.pt-br.json | 16 +++ lang/ui.zh-tw.json | 16 +++ src/components/LanguageDialog.tsx | 187 ++++++++++++++++++++++++----- src/flags.ts | 4 + src/messages/ui.ca.json | 24 ++++ src/messages/ui.en.json | 24 ++++ src/messages/ui.es-es.json | 24 ++++ src/messages/ui.ja.json | 24 ++++ src/messages/ui.ko.json | 24 ++++ src/messages/ui.nl.json | 24 ++++ src/messages/ui.pl.json | 24 ++++ src/messages/ui.pt-br.json | 24 ++++ src/messages/ui.zh-tw.json | 24 ++++ src/settings.tsx | 191 ++++++++++++++++++++++++++++-- 21 files changed, 705 insertions(+), 37 deletions(-) diff --git a/lang/ui.ca.json b/lang/ui.ca.json index 0b69168ee..6106b247e 100644 --- a/lang/ui.ca.json +++ b/lang/ui.ca.json @@ -871,6 +871,22 @@ "defaultMessage": "Idioma", "description": "Language option text" }, + "language-support-checked": { + "defaultMessage": "Supported", + "description": "Aria label for ticked checkbox for language support" + }, + "language-support-unchecked": { + "defaultMessage": "Unsupported", + "description": "Aria label for unticked checkbox for language support" + }, + "language-supported-for": { + "defaultMessage": "Translations supported for:", + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + }, + "language-toast-title": { + "defaultMessage": "Language not fully supported", + "description": "Language support toast notification title" + }, "learn-about-firewall-requirements-action": { "defaultMessage": "Més informació sobre els requisits del tallafoc", "description": "Link to support article for firewall requirements" diff --git a/lang/ui.en.json b/lang/ui.en.json index 14d509367..c0c88012d 100644 --- a/lang/ui.en.json +++ b/lang/ui.en.json @@ -871,6 +871,22 @@ "defaultMessage": "Language", "description": "Language option text" }, + "language-support-checked": { + "defaultMessage": "Supported", + "description": "Aria label for ticked checkbox for language support" + }, + "language-support-unchecked": { + "defaultMessage": "Unsupported", + "description": "Aria label for unticked checkbox for language support" + }, + "language-supported-for": { + "defaultMessage": "Translations supported for:", + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + }, + "language-toast-title": { + "defaultMessage": "Language not fully supported", + "description": "Language support toast notification title" + }, "learn-about-firewall-requirements-action": { "defaultMessage": "Learn about firewall requirements", "description": "Link to support article for firewall requirements" diff --git a/lang/ui.es-es.json b/lang/ui.es-es.json index 838208138..c05c21b62 100644 --- a/lang/ui.es-es.json +++ b/lang/ui.es-es.json @@ -871,6 +871,22 @@ "defaultMessage": "Idioma", "description": "Language option text" }, + "language-support-checked": { + "defaultMessage": "Supported", + "description": "Aria label for ticked checkbox for language support" + }, + "language-support-unchecked": { + "defaultMessage": "Unsupported", + "description": "Aria label for unticked checkbox for language support" + }, + "language-supported-for": { + "defaultMessage": "Translations supported for:", + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + }, + "language-toast-title": { + "defaultMessage": "Language not fully supported", + "description": "Language support toast notification title" + }, "learn-about-firewall-requirements-action": { "defaultMessage": "Conoce los requisitos del cortafuegos", "description": "Link to support article for firewall requirements" diff --git a/lang/ui.ja.json b/lang/ui.ja.json index f6575a79a..b25ac1bf1 100644 --- a/lang/ui.ja.json +++ b/lang/ui.ja.json @@ -871,6 +871,22 @@ "defaultMessage": "言語", "description": "Language option text" }, + "language-support-checked": { + "defaultMessage": "Supported", + "description": "Aria label for ticked checkbox for language support" + }, + "language-support-unchecked": { + "defaultMessage": "Unsupported", + "description": "Aria label for unticked checkbox for language support" + }, + "language-supported-for": { + "defaultMessage": "Translations supported for:", + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + }, + "language-toast-title": { + "defaultMessage": "Language not fully supported", + "description": "Language support toast notification title" + }, "learn-about-firewall-requirements-action": { "defaultMessage": "ファイアウォール要件について調べる", "description": "Link to support article for firewall requirements" diff --git a/lang/ui.ko.json b/lang/ui.ko.json index 0bd800b29..d1e26f6e5 100644 --- a/lang/ui.ko.json +++ b/lang/ui.ko.json @@ -871,6 +871,22 @@ "defaultMessage": "언어 선택", "description": "Language option text" }, + "language-support-checked": { + "defaultMessage": "Supported", + "description": "Aria label for ticked checkbox for language support" + }, + "language-support-unchecked": { + "defaultMessage": "Unsupported", + "description": "Aria label for unticked checkbox for language support" + }, + "language-supported-for": { + "defaultMessage": "Translations supported for:", + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + }, + "language-toast-title": { + "defaultMessage": "Language not fully supported", + "description": "Language support toast notification title" + }, "learn-about-firewall-requirements-action": { "defaultMessage": "방화벽 요구 사항에 대해 알아보기", "description": "Link to support article for firewall requirements" diff --git a/lang/ui.nl.json b/lang/ui.nl.json index cd08bc883..ab382b075 100644 --- a/lang/ui.nl.json +++ b/lang/ui.nl.json @@ -871,6 +871,22 @@ "defaultMessage": "Taal", "description": "Language option text" }, + "language-support-checked": { + "defaultMessage": "Supported", + "description": "Aria label for ticked checkbox for language support" + }, + "language-support-unchecked": { + "defaultMessage": "Unsupported", + "description": "Aria label for unticked checkbox for language support" + }, + "language-supported-for": { + "defaultMessage": "Translations supported for:", + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + }, + "language-toast-title": { + "defaultMessage": "Language not fully supported", + "description": "Language support toast notification title" + }, "learn-about-firewall-requirements-action": { "defaultMessage": "Meer informatie over firewall vereisten", "description": "Link to support article for firewall requirements" diff --git a/lang/ui.pl.json b/lang/ui.pl.json index a36e48a8a..2d9b1c87c 100644 --- a/lang/ui.pl.json +++ b/lang/ui.pl.json @@ -871,6 +871,22 @@ "defaultMessage": "Język", "description": "Language option text" }, + "language-support-checked": { + "defaultMessage": "Supported", + "description": "Aria label for ticked checkbox for language support" + }, + "language-support-unchecked": { + "defaultMessage": "Unsupported", + "description": "Aria label for unticked checkbox for language support" + }, + "language-supported-for": { + "defaultMessage": "Translations supported for:", + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + }, + "language-toast-title": { + "defaultMessage": "Language not fully supported", + "description": "Language support toast notification title" + }, "learn-about-firewall-requirements-action": { "defaultMessage": "Dowiedz się więcej o wymaganiach firewall", "description": "Link to support article for firewall requirements" diff --git a/lang/ui.pt-br.json b/lang/ui.pt-br.json index 7509dfb3c..728688141 100644 --- a/lang/ui.pt-br.json +++ b/lang/ui.pt-br.json @@ -871,6 +871,22 @@ "defaultMessage": "Idioma", "description": "Language option text" }, + "language-support-checked": { + "defaultMessage": "Supported", + "description": "Aria label for ticked checkbox for language support" + }, + "language-support-unchecked": { + "defaultMessage": "Unsupported", + "description": "Aria label for unticked checkbox for language support" + }, + "language-supported-for": { + "defaultMessage": "Translations supported for:", + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + }, + "language-toast-title": { + "defaultMessage": "Language not fully supported", + "description": "Language support toast notification title" + }, "learn-about-firewall-requirements-action": { "defaultMessage": "Saiba mais sobre os requisitos de firewall.", "description": "Link to support article for firewall requirements" diff --git a/lang/ui.zh-tw.json b/lang/ui.zh-tw.json index b3f521183..952387d3d 100644 --- a/lang/ui.zh-tw.json +++ b/lang/ui.zh-tw.json @@ -871,6 +871,22 @@ "defaultMessage": "語言", "description": "Language option text" }, + "language-support-checked": { + "defaultMessage": "Supported", + "description": "Aria label for ticked checkbox for language support" + }, + "language-support-unchecked": { + "defaultMessage": "Unsupported", + "description": "Aria label for unticked checkbox for language support" + }, + "language-supported-for": { + "defaultMessage": "Translations supported for:", + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + }, + "language-toast-title": { + "defaultMessage": "Language not fully supported", + "description": "Language support toast notification title" + }, "learn-about-firewall-requirements-action": { "defaultMessage": "瞭解防火牆要求", "description": "Link to support article for firewall requirements" diff --git a/src/components/LanguageDialog.tsx b/src/components/LanguageDialog.tsx index 51b5951db..ee06459e8 100644 --- a/src/components/LanguageDialog.tsx +++ b/src/components/LanguageDialog.tsx @@ -12,13 +12,32 @@ import { ModalHeader, ModalOverlay, } from "@chakra-ui/modal"; -import { HStack, Icon, Link, SimpleGrid, Text, VStack } from "@chakra-ui/react"; -import { useCallback } from "react"; -import { RiExternalLinkLine } from "react-icons/ri"; -import { FormattedMessage } from "react-intl"; +import { + BoxProps, + HStack, + Icon, + Link, + List, + ListItem, + SimpleGrid, + Stack, + Text, + Tooltip, + VStack, + useToast, +} from "@chakra-ui/react"; +import React, { useCallback, useRef, useState } from "react"; +import { + RiCheckboxBlankLine, + RiCheckboxLine, + RiErrorWarningLine, + RiExternalLinkLine, +} from "react-icons/ri"; +import { FormattedMessage, IntlShape, useIntl } from "react-intl"; import { deployment } from "../deployment"; -import { Language, supportedLanguages } from "../settings"; +import { allLanguages, Language } from "../settings"; import { useStore } from "../store"; +import { flags } from "../flags"; interface LanguageDialogProps { isOpen: boolean; @@ -42,12 +61,12 @@ export const LanguageDialog = ({ }, [onClose, setLanguage] ); - const hasPreviewLanguages = supportedLanguages.some((l) => l.preview); return ( @@ -57,8 +76,8 @@ export const LanguageDialog = ({ - - {supportedLanguages.map((language) => ( + + {allLanguages.map((language) => ( ))} - + + + {" "} - - {hasPreviewLanguages && ( - - * These languages are an early preview of in-progress - translations. - - )} - - @@ -102,27 +115,143 @@ interface LanguageCardProps { } const LanguageCard = ({ language, onChooseLanguage }: LanguageCardProps) => { + const intl = useIntl(); + const [tooltipOpen, setTooltipOpen] = useState(false); + const tooltipRef = useRef(null); + const toast = useToast(); + const handleLanguageSelect = useCallback( + (e: React.MouseEvent) => { + if (e.target !== tooltipRef.current) { + onChooseLanguage(language.id); + if (!fullySupported(language)) { + toast({ + title: intl.formatMessage({ id: "language-toast-title" }), + description: ( + + ), + status: "info", + duration: 5_000, + isClosable: true, + position: "top", + variant: "toast", + }); + } + } + }, + [intl, language, onChooseLanguage, toast] + ); + const handleTooltipClick = useCallback((e: React.MouseEvent) => { + e.stopPropagation(); + setTooltipOpen(true); + }, []); return ( ); }; + +const uiSupported = (language: Language): boolean => + language.ui === true || + (language.ui === "preview" && flags.translationPreview); + +const fullySupported = (language: Language): boolean => { + return uiSupported(language) === true && language.makeCode; +}; + +interface SupportStatementProps extends BoxProps { + language: Language; + intl: IntlShape; +} + +const SupportStatement = ({ + language, + intl, + ...rest +}: SupportStatementProps) => { + return ( + + + {intl.formatMessage({ id: "language-supported-for" })} + + + + Microsoft MakeCode + + + micro:bit CreateAI + + + + ); +}; + +const SupportedListItem = ({ + children, + supported, + intl, +}: { + children: string; + supported: boolean; + intl: IntlShape; +}) => { + return ( + + {" "} + {children} + + ); +}; diff --git a/src/flags.ts b/src/flags.ts index 1f04d93d7..32521e056 100644 --- a/src/flags.ts +++ b/src/flags.ts @@ -24,6 +24,10 @@ export type Flag = * Flag to add a beta warning. Enabled for review and staging site stages. */ | "preReleaseNotice" + /** + * Enables languages that are ready for review. + */ + | "translationPreview" /** * Flag to show links to website content for the CreateAI release. */ diff --git a/src/messages/ui.ca.json b/src/messages/ui.ca.json index 45a79bc3d..fee7277c8 100644 --- a/src/messages/ui.ca.json +++ b/src/messages/ui.ca.json @@ -1519,6 +1519,30 @@ "value": "Idioma" } ], + "language-support-checked": [ + { + "type": 0, + "value": "Supported" + } + ], + "language-support-unchecked": [ + { + "type": 0, + "value": "Unsupported" + } + ], + "language-supported-for": [ + { + "type": 0, + "value": "Translations supported for:" + } + ], + "language-toast-title": [ + { + "type": 0, + "value": "Language not fully supported" + } + ], "learn-about-firewall-requirements-action": [ { "type": 0, diff --git a/src/messages/ui.en.json b/src/messages/ui.en.json index 4e296aae5..5d1b504ef 100644 --- a/src/messages/ui.en.json +++ b/src/messages/ui.en.json @@ -1533,6 +1533,30 @@ "value": "Language" } ], + "language-support-checked": [ + { + "type": 0, + "value": "Supported" + } + ], + "language-support-unchecked": [ + { + "type": 0, + "value": "Unsupported" + } + ], + "language-supported-for": [ + { + "type": 0, + "value": "Translations supported for:" + } + ], + "language-toast-title": [ + { + "type": 0, + "value": "Language not fully supported" + } + ], "learn-about-firewall-requirements-action": [ { "type": 0, diff --git a/src/messages/ui.es-es.json b/src/messages/ui.es-es.json index 1999dd986..78887c9ba 100644 --- a/src/messages/ui.es-es.json +++ b/src/messages/ui.es-es.json @@ -1533,6 +1533,30 @@ "value": "Idioma" } ], + "language-support-checked": [ + { + "type": 0, + "value": "Supported" + } + ], + "language-support-unchecked": [ + { + "type": 0, + "value": "Unsupported" + } + ], + "language-supported-for": [ + { + "type": 0, + "value": "Translations supported for:" + } + ], + "language-toast-title": [ + { + "type": 0, + "value": "Language not fully supported" + } + ], "learn-about-firewall-requirements-action": [ { "type": 0, diff --git a/src/messages/ui.ja.json b/src/messages/ui.ja.json index 40e733cd3..24e88069e 100644 --- a/src/messages/ui.ja.json +++ b/src/messages/ui.ja.json @@ -1513,6 +1513,30 @@ "value": "言語" } ], + "language-support-checked": [ + { + "type": 0, + "value": "Supported" + } + ], + "language-support-unchecked": [ + { + "type": 0, + "value": "Unsupported" + } + ], + "language-supported-for": [ + { + "type": 0, + "value": "Translations supported for:" + } + ], + "language-toast-title": [ + { + "type": 0, + "value": "Language not fully supported" + } + ], "learn-about-firewall-requirements-action": [ { "type": 0, diff --git a/src/messages/ui.ko.json b/src/messages/ui.ko.json index d95111423..fce572d94 100644 --- a/src/messages/ui.ko.json +++ b/src/messages/ui.ko.json @@ -1521,6 +1521,30 @@ "value": "언어 선택" } ], + "language-support-checked": [ + { + "type": 0, + "value": "Supported" + } + ], + "language-support-unchecked": [ + { + "type": 0, + "value": "Unsupported" + } + ], + "language-supported-for": [ + { + "type": 0, + "value": "Translations supported for:" + } + ], + "language-toast-title": [ + { + "type": 0, + "value": "Language not fully supported" + } + ], "learn-about-firewall-requirements-action": [ { "type": 0, diff --git a/src/messages/ui.nl.json b/src/messages/ui.nl.json index 989c04fdc..64c1b8600 100644 --- a/src/messages/ui.nl.json +++ b/src/messages/ui.nl.json @@ -1533,6 +1533,30 @@ "value": "Taal" } ], + "language-support-checked": [ + { + "type": 0, + "value": "Supported" + } + ], + "language-support-unchecked": [ + { + "type": 0, + "value": "Unsupported" + } + ], + "language-supported-for": [ + { + "type": 0, + "value": "Translations supported for:" + } + ], + "language-toast-title": [ + { + "type": 0, + "value": "Language not fully supported" + } + ], "learn-about-firewall-requirements-action": [ { "type": 0, diff --git a/src/messages/ui.pl.json b/src/messages/ui.pl.json index c820e1822..91222b4b2 100644 --- a/src/messages/ui.pl.json +++ b/src/messages/ui.pl.json @@ -1537,6 +1537,30 @@ "value": "Język" } ], + "language-support-checked": [ + { + "type": 0, + "value": "Supported" + } + ], + "language-support-unchecked": [ + { + "type": 0, + "value": "Unsupported" + } + ], + "language-supported-for": [ + { + "type": 0, + "value": "Translations supported for:" + } + ], + "language-toast-title": [ + { + "type": 0, + "value": "Language not fully supported" + } + ], "learn-about-firewall-requirements-action": [ { "type": 0, diff --git a/src/messages/ui.pt-br.json b/src/messages/ui.pt-br.json index a3ee8f4c8..a369f5389 100644 --- a/src/messages/ui.pt-br.json +++ b/src/messages/ui.pt-br.json @@ -1533,6 +1533,30 @@ "value": "Idioma" } ], + "language-support-checked": [ + { + "type": 0, + "value": "Supported" + } + ], + "language-support-unchecked": [ + { + "type": 0, + "value": "Unsupported" + } + ], + "language-supported-for": [ + { + "type": 0, + "value": "Translations supported for:" + } + ], + "language-toast-title": [ + { + "type": 0, + "value": "Language not fully supported" + } + ], "learn-about-firewall-requirements-action": [ { "type": 0, diff --git a/src/messages/ui.zh-tw.json b/src/messages/ui.zh-tw.json index a8a5c9465..a7e9d8e39 100644 --- a/src/messages/ui.zh-tw.json +++ b/src/messages/ui.zh-tw.json @@ -1529,6 +1529,30 @@ "value": "語言" } ], + "language-support-checked": [ + { + "type": 0, + "value": "Supported" + } + ], + "language-support-unchecked": [ + { + "type": 0, + "value": "Unsupported" + } + ], + "language-supported-for": [ + { + "type": 0, + "value": "Translations supported for:" + } + ], + "language-toast-title": [ + { + "type": 0, + "value": "Language not fully supported" + } + ], "learn-about-firewall-requirements-action": [ { "type": 0, diff --git a/src/settings.tsx b/src/settings.tsx index 697b8b633..392e17644 100644 --- a/src/settings.tsx +++ b/src/settings.tsx @@ -4,14 +4,16 @@ * * SPDX-License-Identifier: MIT */ -import { stage } from "./environment"; import { DataSamplesView, TourTriggerName } from "./model"; +type Translation = "preview" | boolean; + export interface Language { id: string; name: string; enName: string; - preview?: boolean; + // Language supported in Classroom UI. + ui: Translation; // Language supported in Microsoft MakeCode editor. makeCode: boolean; } @@ -22,54 +24,231 @@ export const allLanguages: Language[] = [ id: "en", name: "English", enName: "English", + ui: true, + makeCode: true, + }, + { + id: "ar", + name: "العربية", + enName: "Arabic", + ui: false, + makeCode: true, + }, + { + id: "bg", + name: "български", + ui: false, + enName: "Bulgarian", makeCode: true, }, { id: "ca", name: "Català", enName: "Catalan", + ui: true, + makeCode: true, + }, + { + id: "cs", + name: "Čeština", + ui: false, + enName: "Czech", + makeCode: true, + }, + { + id: "cy", + name: "Cymraeg", + ui: true, + enName: "Welsh", + makeCode: true, + }, + { + id: "da", + name: "Dansk", + ui: false, + enName: "Danish", + makeCode: true, + }, + { + id: "de", + name: "Deutsch", + ui: "preview", + enName: "German", + makeCode: true, + }, + { + id: "el", + name: "Ελληνικά", + ui: false, + enName: "Greek", makeCode: true, }, { id: "es-ES", name: "Español", enName: "Spanish", + ui: true, + makeCode: true, + }, + { + id: "fi", + name: "Suomi", + ui: false, + enName: "Finnish", + makeCode: true, + }, + { + id: "fr", + name: "Français", + ui: true, + enName: "French", + makeCode: true, + }, + { + id: "he", + name: "עברית", + ui: false, + enName: "Hebrew", + makeCode: true, + }, + { + id: "hu", + name: "Magyar", + ui: false, + enName: "Hungarian", + makeCode: true, + }, + { + id: "is", + name: "Íslenska", + ui: false, + enName: "Icelandic", + makeCode: true, + }, + { + id: "it", + name: "Italiano", + ui: "preview", + enName: "Italian", makeCode: true, }, { id: "ja", name: "日本語", enName: "Japanese", + ui: true, makeCode: true, }, { id: "ko", name: "한국어", enName: "Korean", + ui: true, makeCode: true, }, { id: "nl", name: "Nederlands", enName: "Dutch", + ui: true, + makeCode: true, + }, + { + id: "nb", + name: "Norsk bokmål", + ui: false, + enName: "Norwegian Bokmal", + makeCode: true, + }, + { + id: "nn-NO", + name: "Norsk nynorsk", + ui: false, + enName: "Norwegian Nynorsk", makeCode: true, }, { id: "pl", name: "Polski", enName: "Polish", + ui: true, makeCode: true, }, { id: "pt-BR", name: "Português (Brasil)", enName: "Portuguese (Brazil)", + ui: true, + makeCode: true, + }, + { + id: "pt-PT", + name: "Português (Portugal)", + ui: false, + enName: "Portuguese (Portugal)", + makeCode: true, + }, + { + id: "ru", + name: "Русский", + ui: false, + enName: "Russian", + makeCode: true, + }, + { + id: "si-LK", + name: "සිංහල", + ui: false, + enName: "Sinhala", + makeCode: true, + }, + { + id: "sk", + name: "Slovenčina", + ui: false, + enName: "Slovak", + makeCode: true, + }, + { + id: "sr", + name: "Srpski", + ui: false, + enName: "Serbian (Latin)", + makeCode: true, + }, + { + id: "sv-SE", + name: "Svenska", + ui: false, + enName: "Swedish", + makeCode: true, + }, + { + id: "tr", + name: "Türkçe", + ui: false, + enName: "Turkish", + makeCode: true, + }, + { + id: "uk", + name: "Українська", + ui: false, + enName: "Ukrainian", + makeCode: true, + }, + { + id: "zh-CN", + name: "简体中文", + ui: false, + enName: "Chinese (Simplified)", makeCode: true, }, { id: "zh-TW", name: "繁體中文", enName: "Chinese (Traditional)", + ui: true, makeCode: true, }, ]; @@ -77,15 +256,11 @@ export const allLanguages: Language[] = [ export const getMakeCodeLang = (languageId: string): string => allLanguages.find((l) => l.id === languageId)?.makeCode ? languageId : "en"; -export const supportedLanguages: Language[] = allLanguages.filter( - (l) => stage !== "production" || !l.preview -); - export const getLanguageFromQuery = (): string => { const searchParams = new URLSearchParams(window.location.search); const l = searchParams.get("l"); - const supportedLanguage = supportedLanguages.find((x) => x.id === l); - return supportedLanguage?.id || supportedLanguages[0].id; + const language = allLanguages.find((x) => x.id === l); + return language?.id || allLanguages[0].id; }; export const defaultSettings: Settings = { From 859e685a91228f5de32fe0ae308503461052a096 Mon Sep 17 00:00:00 2001 From: Grace Date: Wed, 11 Jun 2025 17:17:25 +0100 Subject: [PATCH 02/10] Use beta MakeCode temporarily --- src/components/Editor.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/Editor.tsx b/src/components/Editor.tsx index 5949a467d..92595e38d 100644 --- a/src/components/Editor.tsx +++ b/src/components/Editor.tsx @@ -27,6 +27,9 @@ const Editor = forwardRef(function Editor( return ( Date: Wed, 11 Jun 2025 17:22:15 +0100 Subject: [PATCH 03/10] Run prettier --- src/components/Editor.tsx | 2 +- src/components/LanguageDialog.tsx | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/Editor.tsx b/src/components/Editor.tsx index 92595e38d..fb5164aef 100644 --- a/src/components/Editor.tsx +++ b/src/components/Editor.tsx @@ -29,7 +29,7 @@ const Editor = forwardRef(function Editor( ref={ref} // TODO: To use live MakeCode instead of beta. baseUrl="https://makecode.microbit.org/beta" - queryParams={{ hidelanguage : "1"}} + queryParams={{ hidelanguage: "1" }} controllerId={controllerId} controller={2} lang={getMakeCodeLang(languageId)} diff --git a/src/components/LanguageDialog.tsx b/src/components/LanguageDialog.tsx index ee06459e8..ee6d3bf41 100644 --- a/src/components/LanguageDialog.tsx +++ b/src/components/LanguageDialog.tsx @@ -89,16 +89,16 @@ export const LanguageDialog = ({ - {" "} - - + pl={1} + alignSelf="flex-start" + href={deployment.translationLink} + target="_blank" + rel="noopener" + color="brand.500" + > + {" "} + + From 35084aefbc4d9977f6eae8647b3370daefa306cb Mon Sep 17 00:00:00 2001 From: Grace Date: Thu, 12 Jun 2025 09:14:30 +0100 Subject: [PATCH 04/10] Default UI lang to en when lang is not supported --- src/messages/TranslationProvider.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/messages/TranslationProvider.tsx b/src/messages/TranslationProvider.tsx index a2a861792..1c6c5a5ca 100644 --- a/src/messages/TranslationProvider.tsx +++ b/src/messages/TranslationProvider.tsx @@ -7,11 +7,22 @@ import { useSettings } from "../store"; import { IntlProvider, MessageFormatElement } from "react-intl"; import { ReactNode, useEffect, useState } from "react"; import { retryAsyncLoad } from "./chunk-util"; +import { allLanguages } from "../settings"; +import { flags } from "../flags"; async function loadLocaleData(locale: string) { const lang = locale.toLowerCase(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - return (await import(`./ui.${lang}.json`)).default as Messages; + const languageSetting = allLanguages.find( + l => l.id.toLowerCase() === lang + ); + const importLanguage = + (flags.translationPreview && languageSetting?.ui === "preview") || + languageSetting?.ui === true; + if (importLanguage) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + return (await import(`./ui.${lang}.json`)).default as Messages; + } + return (await import("./ui.en.json")).default; } type Messages = Record | Record; From e840cefc09c4192b6abf23a98cb8442c6b6318e4 Mon Sep 17 00:00:00 2001 From: Grace Date: Thu, 12 Jun 2025 09:23:08 +0100 Subject: [PATCH 05/10] Fix E2E makeCode editor test --- src/e2e/app/makecode-editor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/e2e/app/makecode-editor.ts b/src/e2e/app/makecode-editor.ts index d6dc36238..1513d7b86 100644 --- a/src/e2e/app/makecode-editor.ts +++ b/src/e2e/app/makecode-editor.ts @@ -25,14 +25,14 @@ export class MakeCodeEditor { async switchToJavaScript() { await this.page .frameLocator('iframe[title="MakeCode"]') - .getByRole("option", { name: "Convert code to JavaScript" }) + .getByRole("menuitem", { name: "Convert code to JavaScript" }) .click(); } async switchToBlocks() { await this.page .frameLocator('iframe[title="MakeCode"]') - .getByRole("option", { name: "Convert code to Blocks" }) + .getByRole("menuitem", { name: "Convert code to Blocks" }) .click(); } From 2fff54ac90b6f7119bc69b275bcfc3b3f89b5ebe Mon Sep 17 00:00:00 2001 From: Grace Date: Thu, 12 Jun 2025 09:48:25 +0100 Subject: [PATCH 06/10] Remove reference to Python Editor in strings --- lang/ui.ca.json | 2 +- lang/ui.en.json | 2 +- lang/ui.es-es.json | 2 +- lang/ui.ja.json | 2 +- lang/ui.ko.json | 2 +- lang/ui.nl.json | 2 +- lang/ui.pl.json | 2 +- lang/ui.pt-br.json | 2 +- lang/ui.zh-tw.json | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lang/ui.ca.json b/lang/ui.ca.json index 6106b247e..f41aba9dd 100644 --- a/lang/ui.ca.json +++ b/lang/ui.ca.json @@ -881,7 +881,7 @@ }, "language-supported-for": { "defaultMessage": "Translations supported for:", - "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit CreateAI UI itself)" }, "language-toast-title": { "defaultMessage": "Language not fully supported", diff --git a/lang/ui.en.json b/lang/ui.en.json index c0c88012d..a73f7320b 100644 --- a/lang/ui.en.json +++ b/lang/ui.en.json @@ -881,7 +881,7 @@ }, "language-supported-for": { "defaultMessage": "Translations supported for:", - "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit CreateAI UI itself)" }, "language-toast-title": { "defaultMessage": "Language not fully supported", diff --git a/lang/ui.es-es.json b/lang/ui.es-es.json index c05c21b62..59bcf9bb4 100644 --- a/lang/ui.es-es.json +++ b/lang/ui.es-es.json @@ -881,7 +881,7 @@ }, "language-supported-for": { "defaultMessage": "Translations supported for:", - "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit CreateAI UI itself)" }, "language-toast-title": { "defaultMessage": "Language not fully supported", diff --git a/lang/ui.ja.json b/lang/ui.ja.json index b25ac1bf1..3a31c0b34 100644 --- a/lang/ui.ja.json +++ b/lang/ui.ja.json @@ -881,7 +881,7 @@ }, "language-supported-for": { "defaultMessage": "Translations supported for:", - "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit CreateAI UI itself)" }, "language-toast-title": { "defaultMessage": "Language not fully supported", diff --git a/lang/ui.ko.json b/lang/ui.ko.json index d1e26f6e5..dd0e200c2 100644 --- a/lang/ui.ko.json +++ b/lang/ui.ko.json @@ -881,7 +881,7 @@ }, "language-supported-for": { "defaultMessage": "Translations supported for:", - "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit CreateAI UI itself)" }, "language-toast-title": { "defaultMessage": "Language not fully supported", diff --git a/lang/ui.nl.json b/lang/ui.nl.json index ab382b075..a5872175a 100644 --- a/lang/ui.nl.json +++ b/lang/ui.nl.json @@ -881,7 +881,7 @@ }, "language-supported-for": { "defaultMessage": "Translations supported for:", - "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit CreateAI UI itself)" }, "language-toast-title": { "defaultMessage": "Language not fully supported", diff --git a/lang/ui.pl.json b/lang/ui.pl.json index 2d9b1c87c..d69163b0b 100644 --- a/lang/ui.pl.json +++ b/lang/ui.pl.json @@ -881,7 +881,7 @@ }, "language-supported-for": { "defaultMessage": "Translations supported for:", - "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit CreateAI UI itself)" }, "language-toast-title": { "defaultMessage": "Language not fully supported", diff --git a/lang/ui.pt-br.json b/lang/ui.pt-br.json index 728688141..234b43a2d 100644 --- a/lang/ui.pt-br.json +++ b/lang/ui.pt-br.json @@ -881,7 +881,7 @@ }, "language-supported-for": { "defaultMessage": "Translations supported for:", - "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit CreateAI UI itself)" }, "language-toast-title": { "defaultMessage": "Language not fully supported", diff --git a/lang/ui.zh-tw.json b/lang/ui.zh-tw.json index 952387d3d..c6f0ecda7 100644 --- a/lang/ui.zh-tw.json +++ b/lang/ui.zh-tw.json @@ -881,7 +881,7 @@ }, "language-supported-for": { "defaultMessage": "Translations supported for:", - "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit Python Editor, micro:bit CreateAI UI itself)" + "description": "Text introducing list of translated areas for a given language (areas: Microsoft MakeCode, micro:bit CreateAI UI itself)" }, "language-toast-title": { "defaultMessage": "Language not fully supported", From 8140531dc89be771594128a783c67663daeddbca Mon Sep 17 00:00:00 2001 From: Grace Date: Thu, 12 Jun 2025 10:02:39 +0100 Subject: [PATCH 07/10] Fix previewTranslation flag and reordering tweaks --- src/flags.ts | 13 +++++++------ src/settings.tsx | 38 +++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/flags.ts b/src/flags.ts index 32521e056..e0f7dc6c4 100644 --- a/src/flags.ts +++ b/src/flags.ts @@ -45,17 +45,18 @@ interface FlagMetadata { const allFlags: FlagMetadata[] = [ // Alphabetical order. + { name: "exampleOptInA", defaultOnStages: ["review", "staging"] }, + { name: "exampleOptInB", defaultOnStages: [] }, { name: "devtools", defaultOnStages: ["local"] }, - { - name: "websiteContent", - defaultOnStages: ["local", "review", "staging", "production"], - }, { name: "preReleaseNotice", defaultOnStages: ["staging"], }, - { name: "exampleOptInA", defaultOnStages: ["review", "staging"] }, - { name: "exampleOptInB", defaultOnStages: [] }, + { name: "translationPreview", defaultOnStages: [] }, + { + name: "websiteContent", + defaultOnStages: ["local", "review", "staging", "production"], + }, ]; type Flags = Record; diff --git a/src/settings.tsx b/src/settings.tsx index 392e17644..2580488fd 100644 --- a/src/settings.tsx +++ b/src/settings.tsx @@ -37,8 +37,8 @@ export const allLanguages: Language[] = [ { id: "bg", name: "български", - ui: false, enName: "Bulgarian", + ui: false, makeCode: true, }, { @@ -51,8 +51,8 @@ export const allLanguages: Language[] = [ { id: "cs", name: "Čeština", - ui: false, enName: "Czech", + ui: false, makeCode: true, }, { @@ -65,8 +65,8 @@ export const allLanguages: Language[] = [ { id: "da", name: "Dansk", - ui: false, enName: "Danish", + ui: false, makeCode: true, }, { @@ -79,8 +79,8 @@ export const allLanguages: Language[] = [ { id: "el", name: "Ελληνικά", - ui: false, enName: "Greek", + ui: false, makeCode: true, }, { @@ -93,8 +93,8 @@ export const allLanguages: Language[] = [ { id: "fi", name: "Suomi", - ui: false, enName: "Finnish", + ui: false, makeCode: true, }, { @@ -107,22 +107,22 @@ export const allLanguages: Language[] = [ { id: "he", name: "עברית", - ui: false, enName: "Hebrew", + ui: false, makeCode: true, }, { id: "hu", name: "Magyar", - ui: false, enName: "Hungarian", + ui: false, makeCode: true, }, { id: "is", name: "Íslenska", - ui: false, enName: "Icelandic", + ui: false, makeCode: true, }, { @@ -156,15 +156,15 @@ export const allLanguages: Language[] = [ { id: "nb", name: "Norsk bokmål", - ui: false, enName: "Norwegian Bokmal", + ui: false, makeCode: true, }, { id: "nn-NO", name: "Norsk nynorsk", - ui: false, enName: "Norwegian Nynorsk", + ui: false, makeCode: true, }, { @@ -184,64 +184,64 @@ export const allLanguages: Language[] = [ { id: "pt-PT", name: "Português (Portugal)", - ui: false, enName: "Portuguese (Portugal)", + ui: false, makeCode: true, }, { id: "ru", name: "Русский", - ui: false, enName: "Russian", + ui: false, makeCode: true, }, { id: "si-LK", name: "සිංහල", - ui: false, enName: "Sinhala", + ui: false, makeCode: true, }, { id: "sk", name: "Slovenčina", - ui: false, enName: "Slovak", + ui: false, makeCode: true, }, { id: "sr", name: "Srpski", - ui: false, enName: "Serbian (Latin)", + ui: false, makeCode: true, }, { id: "sv-SE", name: "Svenska", - ui: false, enName: "Swedish", + ui: false, makeCode: true, }, { id: "tr", name: "Türkçe", - ui: false, enName: "Turkish", + ui: false, makeCode: true, }, { id: "uk", name: "Українська", - ui: false, enName: "Ukrainian", + ui: false, makeCode: true, }, { id: "zh-CN", name: "简体中文", - ui: false, enName: "Chinese (Simplified)", + ui: false, makeCode: true, }, { From 071c5ff6e6ac2ca34e2cc6e2d71204a7c56961c6 Mon Sep 17 00:00:00 2001 From: Grace Date: Thu, 12 Jun 2025 13:22:58 +0100 Subject: [PATCH 08/10] Fix language settings --- src/settings.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/settings.tsx b/src/settings.tsx index 2580488fd..24baff0b8 100644 --- a/src/settings.tsx +++ b/src/settings.tsx @@ -58,8 +58,8 @@ export const allLanguages: Language[] = [ { id: "cy", name: "Cymraeg", - ui: true, enName: "Welsh", + ui: false, makeCode: true, }, { @@ -72,8 +72,8 @@ export const allLanguages: Language[] = [ { id: "de", name: "Deutsch", - ui: "preview", enName: "German", + ui: false, makeCode: true, }, { @@ -100,8 +100,8 @@ export const allLanguages: Language[] = [ { id: "fr", name: "Français", - ui: true, enName: "French", + ui: false, makeCode: true, }, { @@ -128,8 +128,8 @@ export const allLanguages: Language[] = [ { id: "it", name: "Italiano", - ui: "preview", enName: "Italian", + ui: false, makeCode: true, }, { From 8326d525b5d532ee97c7706dffe895f12813b345 Mon Sep 17 00:00:00 2001 From: Grace Date: Thu, 12 Jun 2025 13:47:47 +0100 Subject: [PATCH 09/10] Handle editorVersion query string param --- src/components/Editor.tsx | 4 ++-- src/editor-version.ts | 13 +++++++++++++ src/pages/HomePage.tsx | 4 ++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 src/editor-version.ts diff --git a/src/components/Editor.tsx b/src/components/Editor.tsx index fb5164aef..8c0ca175f 100644 --- a/src/components/Editor.tsx +++ b/src/components/Editor.tsx @@ -11,6 +11,7 @@ import React, { forwardRef } from "react"; import { useProject } from "../hooks/project-hooks"; import { getMakeCodeLang } from "../settings"; import { useSettings } from "../store"; +import { getEditorVersionOverride } from "../editor-version"; const controllerId = "MicrobitMachineLearningTool"; @@ -27,13 +28,12 @@ const Editor = forwardRef(function Editor( return ( diff --git a/src/editor-version.ts b/src/editor-version.ts new file mode 100644 index 000000000..d6b6df664 --- /dev/null +++ b/src/editor-version.ts @@ -0,0 +1,13 @@ +const editorVersionOverrideSessionStorageKey = "editorVersionOverride"; +export const setEditorVersionOverride = (version: string | undefined) => { + if (version) { + sessionStorage.setItem(editorVersionOverrideSessionStorageKey, version); + } else { + sessionStorage.removeItem(editorVersionOverrideSessionStorageKey); + } +}; +export const getEditorVersionOverride = (): string | undefined => { + return ( + sessionStorage.getItem(editorVersionOverrideSessionStorageKey) ?? undefined + ); +}; diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 27f6d5bab..2b54a50c3 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -36,8 +36,12 @@ import { userGuideUrl, } from "../utils/external-links"; import { useSettings } from "../store"; +import { useSearchParams } from "react-router-dom"; +import { setEditorVersionOverride } from "../editor-version"; const HomePage = () => { + const [params] = useSearchParams(); + setEditorVersionOverride(params.get("editorVersion") || undefined); const navigate = useNavigate(); const handleGetStarted = useCallback(() => { navigate(createNewPageUrl()); From 0b532b3d5fc3924bb122d78511f74733628aacfe Mon Sep 17 00:00:00 2001 From: Grace Date: Thu, 12 Jun 2025 13:54:22 +0100 Subject: [PATCH 10/10] Revert "Fix E2E makeCode editor test" This reverts commit e840cefc09c4192b6abf23a98cb8442c6b6318e4. --- src/e2e/app/makecode-editor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/e2e/app/makecode-editor.ts b/src/e2e/app/makecode-editor.ts index 1513d7b86..d6dc36238 100644 --- a/src/e2e/app/makecode-editor.ts +++ b/src/e2e/app/makecode-editor.ts @@ -25,14 +25,14 @@ export class MakeCodeEditor { async switchToJavaScript() { await this.page .frameLocator('iframe[title="MakeCode"]') - .getByRole("menuitem", { name: "Convert code to JavaScript" }) + .getByRole("option", { name: "Convert code to JavaScript" }) .click(); } async switchToBlocks() { await this.page .frameLocator('iframe[title="MakeCode"]') - .getByRole("menuitem", { name: "Convert code to Blocks" }) + .getByRole("option", { name: "Convert code to Blocks" }) .click(); }