Skip to content

Add "config" message for translation #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/board/buttons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ export class Button {
constructor(
private id: "buttonA" | "buttonB",
private element: SVGElement,
label: string,
private label: () => string,
private onChange: (change: Partial<State>) => void
) {
this._presses = 0;
this.state = new RangeSensor(id, 0, 1, 0, undefined);

this.element.setAttribute("role", "button");
this.element.setAttribute("tabindex", "0");
this.element.ariaLabel = label;
this.element.style.cursor = "pointer";

this.keyListener = (e) => {
Expand Down Expand Up @@ -64,6 +63,10 @@ export class Button {
this.element.addEventListener("mouseleave", this.mouseLeaveListener);
}

updateTranslations() {
this.element.ariaLabel = this.label();
}

setValue(value: any) {
this.setValueInternal(value, false);
}
Expand Down
54 changes: 47 additions & 7 deletions src/board/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,22 @@ export class Board {

private epoch: number | undefined;

// The language and translations can be changed via the "config" message.
private language: string = "en";
private translations: Record<string, string> = {
"button-a": "Button A",
"button-b": "Button B",
"touch-logo": "Touch logo",
"start-simulator": "Start simulator",
};
formattedMessage = ({ id }: { id: string }): string => {
const result = this.translations[id];
if (!result) {
console.trace(`No string for code ${id}`);
}
return result ?? id;
};

constructor(
public operations: WebAssemblyOperations,
private notifications: Notifications,
Expand All @@ -70,26 +86,28 @@ export class Board {
new Button(
"buttonA",
this.svg.querySelector("#ButtonA")!,
"button A",
() => this.formattedMessage({ id: "button-a" }),
onChange
),
new Button(
"buttonB",
this.svg.querySelector("#ButtonB")!,
"button B",
() => this.formattedMessage({ id: "button-b" }),
onChange
),
];
this.pins = Array(33);
this.pins[MICROBIT_HAL_PIN_FACE] = new Pin(
"pinLogo",
this.svg.querySelector("#Logo")!,
"logo",
{
element: this.svg.querySelector("#Logo")!,
label: () => this.formattedMessage({ id: "touch-logo" }),
},
onChange
);
this.pins[MICROBIT_HAL_PIN_P0] = new Pin("pin0", null, "pin 0", onChange);
this.pins[MICROBIT_HAL_PIN_P1] = new Pin("pin1", null, "pin 1", onChange);
this.pins[MICROBIT_HAL_PIN_P2] = new Pin("pin2", null, "pin 2", onChange);
this.pins[MICROBIT_HAL_PIN_P0] = new Pin("pin0", null, onChange);
this.pins[MICROBIT_HAL_PIN_P1] = new Pin("pin1", null, onChange);
this.pins[MICROBIT_HAL_PIN_P2] = new Pin("pin2", null, onChange);
this.audio = new Audio();
this.temperature = new RangeSensor("temperature", -5, 50, 21, "°C");
this.accelerometer = new Accelerometer(onChange);
Expand Down Expand Up @@ -121,6 +139,23 @@ export class Board {
this.playButton.addEventListener("click", () =>
this.notifications.onRequestFlash()
);

this.updateTranslationsInternal();
}

updateTranslations(language: string, translations: Record<string, string>) {
this.language = language;
this.translations = translations;
this.updateTranslationsInternal();
}

private updateTranslationsInternal() {
document.documentElement.lang = this.language;
this.playButton.ariaLabel = this.formattedMessage({
id: "start-simulator",
});
this.buttons.forEach((b) => b.updateTranslations());
this.pins.forEach((b) => b.updateTranslations());
}

getState(): State {
Expand Down Expand Up @@ -388,6 +423,11 @@ export const createMessageListener = (board: Board) => (e: MessageEvent) => {
if (e.source === window.parent) {
const { data } = e;
switch (data.kind) {
case "config": {
const { language, translations } = data;
board.updateTranslations(language, translations);
break;
}
case "flash": {
const { filesystem } = data;
if (!isFileSystem(filesystem)) {
Expand Down
36 changes: 21 additions & 15 deletions src/board/pins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,16 @@ export class Pin {

constructor(
private id: "pin0" | "pin1" | "pin2" | "pinLogo",
private element: SVGElement | null,
label: string,
private ui: { element: SVGElement; label: () => string } | null,
private onChange: (changes: Partial<State>) => void
) {
this.state = new RangeSensor(id, 0, 1, 0, undefined);

if (this.element) {
this.element.setAttribute("role", "button");
this.element.setAttribute("tabindex", "0");
this.element.ariaLabel = label;
this.element.style.cursor = "pointer";
if (this.ui) {
const { element, label } = this.ui;
element.setAttribute("role", "button");
element.setAttribute("tabindex", "0");
element.style.cursor = "pointer";
}

this.keyListener = (e) => {
Expand Down Expand Up @@ -57,12 +56,13 @@ export class Pin {
}
};

if (this.element) {
this.element.addEventListener("mousedown", this.mouseDownListener);
this.element.addEventListener("mouseup", this.mouseUpListener);
this.element.addEventListener("keydown", this.keyListener);
this.element.addEventListener("keyup", this.keyListener);
this.element.addEventListener("mouseleave", this.mouseLeaveListener);
if (this.ui) {
const { element } = this.ui;
element.addEventListener("mousedown", this.mouseDownListener);
element.addEventListener("mouseup", this.mouseUpListener);
element.addEventListener("keydown", this.keyListener);
element.addEventListener("keyup", this.keyListener);
element.addEventListener("mouseleave", this.mouseLeaveListener);
}
}

Expand Down Expand Up @@ -98,10 +98,16 @@ export class Pin {
return !!this.state.value;
}

updateTranslations() {
if (this.ui) {
this.ui.element.ariaLabel = this.ui.label();
}
}

render() {
if (this.element) {
if (this.ui) {
const fill = !!this.state.value ? "red" : "url(#an)";
this.element.querySelectorAll("path").forEach((p) => {
this.ui.element.querySelectorAll("path").forEach((p) => {
p.style.fill = fill;
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/simulator.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<title>Simulator</title>
<meta charset="UTF-8" />
Expand Down