@@ -58,6 +58,22 @@ export class Board {
5858
5959 private epoch : number | undefined ;
6060
61+ // The language and translations can be changed via the "config" message.
62+ private language : string = "en" ;
63+ private translations : Record < string , string > = {
64+ "button-a" : "Button A" ,
65+ "button-b" : "Button B" ,
66+ "touch-logo" : "Touch logo" ,
67+ "start-simulator" : "Start simulator" ,
68+ } ;
69+ formattedMessage = ( { id } : { id : string } ) : string => {
70+ const result = this . translations [ id ] ;
71+ if ( ! result ) {
72+ console . trace ( `No string for code ${ id } ` ) ;
73+ }
74+ return result ?? id ;
75+ } ;
76+
6177 constructor (
6278 public operations : WebAssemblyOperations ,
6379 private notifications : Notifications ,
@@ -72,26 +88,28 @@ export class Board {
7288 new Button (
7389 "buttonA" ,
7490 this . svg . querySelector ( "#ButtonA" ) ! ,
75- "button A" ,
91+ ( ) => this . formattedMessage ( { id : "button-a" } ) ,
7692 onChange
7793 ) ,
7894 new Button (
7995 "buttonB" ,
8096 this . svg . querySelector ( "#ButtonB" ) ! ,
81- "button B" ,
97+ ( ) => this . formattedMessage ( { id : "button-b" } ) ,
8298 onChange
8399 ) ,
84100 ] ;
85101 this . pins = Array ( 33 ) ;
86102 this . pins [ MICROBIT_HAL_PIN_FACE ] = new Pin (
87103 "pinLogo" ,
88- this . svg . querySelector ( "#Logo" ) ! ,
89- "logo" ,
104+ {
105+ element : this . svg . querySelector ( "#Logo" ) ! ,
106+ label : ( ) => this . formattedMessage ( { id : "touch-logo" } ) ,
107+ } ,
90108 onChange
91109 ) ;
92- this . pins [ MICROBIT_HAL_PIN_P0 ] = new Pin ( "pin0" , null , "pin 0" , onChange ) ;
93- this . pins [ MICROBIT_HAL_PIN_P1 ] = new Pin ( "pin1" , null , "pin 1" , onChange ) ;
94- this . pins [ MICROBIT_HAL_PIN_P2 ] = new Pin ( "pin2" , null , "pin 2" , onChange ) ;
110+ this . pins [ MICROBIT_HAL_PIN_P0 ] = new Pin ( "pin0" , null , onChange ) ;
111+ this . pins [ MICROBIT_HAL_PIN_P1 ] = new Pin ( "pin1" , null , onChange ) ;
112+ this . pins [ MICROBIT_HAL_PIN_P2 ] = new Pin ( "pin2" , null , onChange ) ;
95113 this . audio = new Audio ( ) ;
96114 this . temperature = new RangeSensor ( "temperature" , - 5 , 50 , 21 , "°C" ) ;
97115 this . accelerometer = new Accelerometer ( onChange ) ;
@@ -123,6 +141,23 @@ export class Board {
123141 this . playButton . addEventListener ( "click" , ( ) =>
124142 this . notifications . onRequestFlash ( )
125143 ) ;
144+
145+ this . updateTranslationsInternal ( ) ;
146+ }
147+
148+ updateTranslations ( language : string , translations : Record < string , string > ) {
149+ this . language = language ;
150+ this . translations = translations ;
151+ this . updateTranslationsInternal ( ) ;
152+ }
153+
154+ private updateTranslationsInternal ( ) {
155+ document . documentElement . lang = this . language ;
156+ this . playButton . ariaLabel = this . formattedMessage ( {
157+ id : "start-simulator" ,
158+ } ) ;
159+ this . buttons . forEach ( ( b ) => b . updateTranslations ( ) ) ;
160+ this . pins . forEach ( ( b ) => b . updateTranslations ( ) ) ;
126161 }
127162
128163 getState ( ) : State {
@@ -499,6 +534,11 @@ export const createMessageListener = (board: Board) => (e: MessageEvent) => {
499534 if ( e . source === window . parent ) {
500535 const { data } = e ;
501536 switch ( data . kind ) {
537+ case "config" : {
538+ const { language, translations } = data ;
539+ board . updateTranslations ( language , translations ) ;
540+ break ;
541+ }
502542 case "flash" : {
503543 const { filesystem } = data ;
504544 if ( ! isFileSystem ( filesystem ) ) {
0 commit comments