diff --git a/app-emulation/unreal_speccy_portable/patches/unreal_speccy_portable-0.0.86.18.patchset b/app-emulation/unreal_speccy_portable/patches/unreal_speccy_portable-0.0.86.18.patchset
index bf8ec653a..277e6cf52 100644
--- a/app-emulation/unreal_speccy_portable/patches/unreal_speccy_portable-0.0.86.18.patchset
+++ b/app-emulation/unreal_speccy_portable/patches/unreal_speccy_portable-0.0.86.18.patchset
@@ -1,4 +1,4 @@
-From e0eb2e98f0aebc5abae2e7fe7153eb7be7b6bb29 Mon Sep 17 00:00:00 2001
+From 349485048283a10e1b5bb4e8d51688aef6c9be2d Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Fri, 25 Jun 2021 23:44:52 +1000
Subject: Add Haiku support
@@ -2558,7 +2558,7 @@ index 0000000..2c5848b
+#endif
diff --git a/platform/haiku/haiku_window.cpp b/platform/haiku/haiku_window.cpp
new file mode 100644
-index 0000000..113c223
+index 0000000..43cec2a
--- /dev/null
+++ b/platform/haiku/haiku_window.cpp
@@ -0,0 +1,1490 @@
@@ -4451,5 +4451,900 @@ index 0000000..20c1207
+ $"000000000000403489C65D18C604D3"
+};
--
-2.30.2
+2.37.3
+
+
+From b3236786139f9d86b0647e11cdfefdc9bdcaa139 Mon Sep 17 00:00:00 2001
+From: Gerasim Troeglazov <3dEyes@gmail.com>
+Date: Sat, 6 May 2023 22:24:44 +1000
+Subject: Fix version
+
+
+diff --git a/platform/haiku/resources.rdef b/platform/haiku/resources.rdef
+index bd831f3..e12a1d1 100644
+--- a/platform/haiku/resources.rdef
++++ b/platform/haiku/resources.rdef
+@@ -6,7 +6,7 @@ resource app_version {
+ major = 0,
+ middle = 0,
+ minor = 86,
+- variety = 17,
++ variety = 18,
+ internal = 0,
+ short_info = "Unreal Speccy Portable",
+ long_info = "Portable ZX-Spectrum emulator"
+--
+2.37.3
+
+
+From 9a8ab01ab90dc9a131dfc7ced2e24f3e50b948b1 Mon Sep 17 00:00:00 2001
+From: Gerasim Troeglazov <3dEyes@gmail.com>
+Date: Sat, 6 May 2023 22:25:22 +1000
+Subject: Add LocaleKit support
+
+
+diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt
+index 1c44a48..3dec766 100644
+--- a/build/cmake/CMakeLists.txt
++++ b/build/cmake/CMakeLists.txt
+@@ -370,7 +370,7 @@ source_group("platform\\haiku" FILES ${SRCCXX_PLATFORM_HAIKU})
+ add_platform_io_stuff()
+
+ add_executable(${PROJECT} WIN32 ${SRCCXX} ${SRCC} ${SRCH})
+-target_link_libraries(${PROJECT} -lbe -lmedia -ldevice -lgame -ltracker -lpng)
++target_link_libraries(${PROJECT} -lbe -lmedia -ldevice -lgame -ltracker -llocalestub -lpng)
+
+ elseif(USE_SDL)
+
+diff --git a/platform/haiku/haiku_keyboard_window.cpp b/platform/haiku/haiku_keyboard_window.cpp
+index 28943d1..6daf943 100644
+--- a/platform/haiku/haiku_keyboard_window.cpp
++++ b/platform/haiku/haiku_keyboard_window.cpp
+@@ -18,6 +18,9 @@ along with this program. If not, see .
+
+ #include "haiku_keyboard_window.h"
+
++#undef B_TRANSLATION_CONTEXT
++#define B_TRANSLATION_CONTEXT "USPKeyboardWindow"
++
+ static zxbutton zxkeymap[] = {
+ {100, ZXB_BUTTON, "BREAK", NULL, NULL, -1, NULL, NULL, 0x01 },
+ {100, ZXB_SEPARATOR, NULL, NULL, NULL, -1, NULL, NULL, 0x00 },
+@@ -279,7 +282,7 @@ ZXButton::MouseUp(BPoint where)
+ }
+
+ KeyboardWindow::KeyboardWindow(BRect frame, BWindow *win)
+-: BWindow(frame, "Keyboard layout", B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
++: BWindow(frame, B_TRANSLATE("Keyboard layout"), B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
+ B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK),
+ fButtonSize(48),
+ fButtonSpace(1),
+diff --git a/platform/haiku/haiku_keyboard_window.h b/platform/haiku/haiku_keyboard_window.h
+index 5ba8fdf..79fef9a 100644
+--- a/platform/haiku/haiku_keyboard_window.h
++++ b/platform/haiku/haiku_keyboard_window.h
+@@ -24,6 +24,7 @@ along with this program. If not, see .
+ #include
+ #include
+ #include
++#include
+
+ #define ZXB_BUTTON 0
+ #define ZXB_SEPARATOR 1
+diff --git a/platform/haiku/haiku_web_window.cpp b/platform/haiku/haiku_web_window.cpp
+index 0f3e89f..db87012 100644
+--- a/platform/haiku/haiku_web_window.cpp
++++ b/platform/haiku/haiku_web_window.cpp
+@@ -25,6 +25,9 @@ along with this program. If not, see .
+ #include "haiku_web_window.h"
+ #include "haiku_list_item.h"
+
++#undef B_TRANSLATION_CONTEXT
++#define B_TRANSLATION_CONTEXT "USPWebWindow"
++
+ namespace xIo
+ {
+ eFileSelect* FileSelectWEB(const char* path);
+@@ -35,7 +38,7 @@ namespace xPlatform
+ {
+
+ WebWindow::WebWindow(BRect frame, BWindow *win)
+-: BWindow(frame, "Open file from web...", B_DOCUMENT_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_CLOSE_ON_ESCAPE),
++: BWindow(frame, B_TRANSLATE("Open file from web" B_UTF8_ELLIPSIS), B_DOCUMENT_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_CLOSE_ON_ESCAPE),
+ fMainWindow(win)
+ {
+ BFont font(be_plain_font);
+@@ -70,10 +73,10 @@ WebWindow::WebWindow(BRect frame, BWindow *win)
+ fLastDownloadedPath.SetTo("/boot/home/config/settings/USP");
+
+ fMenuBar = new BMenuBar("menu_bar", B_ITEMS_IN_ROW, B_INVALIDATE_AFTER_LAYOUT);
+- BMenu* menu = new BMenu("File");
+- menu->AddItem(new BMenuItem("Open", new BMessage(kFileInvocated), 'O'));
+- menu->AddItem(new BMenuItem("Download file", new BMessage(kFileDownload), 'D'));
+- menu->AddItem(new BMenuItem("Open download folder", new BMessage(kFileOpenDowloadFolder), 'J'));
++ BMenu* menu = new BMenu(B_TRANSLATE("File"));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Open"), new BMessage(kFileInvocated), 'O'));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Download file"), new BMessage(kFileDownload), 'D'));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Open download folder"), new BMessage(kFileOpenDowloadFolder), 'J'));
+ fMenuBar->AddItem(menu);
+ menu->SetTargetForItems(this);
+
+@@ -90,13 +93,13 @@ WebWindow::WebWindow(BRect frame, BWindow *win)
+ fUpButton->SetIcon(fUpIcon, 0);
+ fUpButton->SetFlat(true);
+
+- fCancelButton = new BButton("Cancel", new BMessage(kCancelButtonPush));
+- fOpenButton = new BButton("Open", new BMessage(kOpenButtonPush));
++ fCancelButton = new BButton(B_TRANSLATE("Cancel"), new BMessage(kCancelButtonPush));
++ fOpenButton = new BButton(B_TRANSLATE("Open"), new BMessage(kOpenButtonPush));
+ fOpenButton->MakeDefault(true);
+
+ BFont smallFont(be_plain_font);
+ smallFont.SetSize(ceilf(font.Size() * 0.75));
+- fStatusView = new BStringView("list status", "Items");
++ fStatusView = new BStringView("list status", B_TRANSLATE("items"));
+ fStatusView->SetFont(&smallFont, B_FONT_SIZE);
+ fStatusView->SetAlignment(B_ALIGN_LEFT);
+
+@@ -206,7 +209,7 @@ WebWindow::UpdateList(void)
+ fUpButton->SetEnabled(pathList.CountStrings() != 0);
+
+ BString statusText;
+- statusText << " " << fListView->CountItems() << " items ";
++ statusText << " " << fListView->CountItems() << " " << B_TRANSLATE("items") << " ";
+ fStatusView->SetText(statusText);
+ }
+
+diff --git a/platform/haiku/haiku_web_window.h b/platform/haiku/haiku_web_window.h
+index 2c5848b..fc9ddf2 100644
+--- a/platform/haiku/haiku_web_window.h
++++ b/platform/haiku/haiku_web_window.h
+@@ -30,6 +30,7 @@ along with this program. If not, see .
+ #include
+ #include
+ #include
++#include
+
+ const uint32 kFileInvocated = 'SINV';
+ const uint32 kFileDownload = 'FDNL';
+diff --git a/platform/haiku/haiku_window.cpp b/platform/haiku/haiku_window.cpp
+index 43cec2a..7fd7e9c 100644
+--- a/platform/haiku/haiku_window.cpp
++++ b/platform/haiku/haiku_window.cpp
+@@ -24,6 +24,9 @@ along with this program. If not, see .
+ #include "haiku_app.h"
+ #include "haiku_window.h"
+
++#undef B_TRANSLATION_CONTEXT
++#define B_TRANSLATION_CONTEXT "USPWindow"
++
+ namespace xPlatform
+ {
+
+@@ -101,22 +104,22 @@ HaikuPlatformWindow::HaikuPlatformWindow(BRect frame, int w, int h, const char*
+ fStateInfoTimer(0)
+ {
+ fMenuBar = new BMenuBar("menu_bar", B_ITEMS_IN_ROW, B_INVALIDATE_AFTER_LAYOUT);
+- BMenu* menu = new BMenu("File");
+- BMenuItem *item = new BMenuItem(BRecentFilesList::NewFileListMenu("Open" B_UTF8_ELLIPSIS,
++ BMenu* menu = new BMenu(B_TRANSLATE("File"));
++ BMenuItem *item = new BMenuItem(BRecentFilesList::NewFileListMenu(B_TRANSLATE("Open" B_UTF8_ELLIPSIS),
+ NULL, NULL, this, 9, true, NULL, APP_SIGNATURE),
+ new BMessage(kFileOpen));
+ item->SetShortcut('O', 0);
+ menu->AddItem(item);
+- menu->AddItem(new BMenuItem("Open from web" B_UTF8_ELLIPSIS, new BMessage(kFileOpenWeb)));
+- menu->AddItem(new BMenuItem("Save" B_UTF8_ELLIPSIS, new BMessage(kFileSave), 'S'));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Open from web" B_UTF8_ELLIPSIS), new BMessage(kFileOpenWeb)));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Save" B_UTF8_ELLIPSIS), new BMessage(kFileSave), 'S'));
+ menu->AddSeparatorItem();
+- menu->AddItem(new BMenuItem("Save screenshot" B_UTF8_ELLIPSIS, new BMessage(kFileSaveScreen)));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Save screenshot" B_UTF8_ELLIPSIS), new BMessage(kFileSaveScreen)));
+ menu->AddSeparatorItem();
+- menu->AddItem(new BMenuItem("Quick load", new BMessage(kFileQuickOpen), 'O', B_SHIFT_KEY));
+- fQuickSaveMenuItem = new BMenuItem("Quick save", new BMessage(kFileQuickSave), 'S', B_SHIFT_KEY);
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Quick load"), new BMessage(kFileQuickOpen), 'O', B_SHIFT_KEY));
++ fQuickSaveMenuItem = new BMenuItem(B_TRANSLATE("Quick save"), new BMessage(kFileQuickSave), 'S', B_SHIFT_KEY);
+ fQuickSaveMenuItem->SetEnabled(false);
+ menu->AddItem(fQuickSaveMenuItem);
+- fQuickSaveSlotMenu = new BMenu("Save slot");
++ fQuickSaveSlotMenu = new BMenu(B_TRANSLATE("Save slot"));
+ for (int slot = 1; slot < 10; slot++) {
+ BMessage *message = new BMessage(kFileQuickSaveSlot);
+ message->AddInt32("slot", slot);
+@@ -127,65 +130,65 @@ HaikuPlatformWindow::HaikuPlatformWindow(BRect frame, int w, int h, const char*
+ fQuickSaveSlotMenu->SetRadioMode(true);
+ menu->AddItem(fQuickSaveSlotMenu);
+ menu->AddSeparatorItem();
+- fAutoPlayMenuItem = new BMenuItem("Auto launch programs", new BMessage(kFileAutoPlay));
++ fAutoPlayMenuItem = new BMenuItem(B_TRANSLATE("Auto launch programs"), new BMessage(kFileAutoPlay));
+ menu->AddItem(fAutoPlayMenuItem);
+ menu->AddSeparatorItem();
+- menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"), new BMessage(B_QUIT_REQUESTED), 'Q'));
+ fMenuBar->AddItem(menu);
+- menu = new BMenu("View");
+- menu->AddItem(new BMenuItem("100% scale", new BMessage(kViewScale1x), '1'));
+- menu->AddItem(new BMenuItem("200% scale", new BMessage(kViewScale2x), '2'));
+- menu->AddItem(new BMenuItem("300% scale", new BMessage(kViewScale3x), '3'));
++ menu = new BMenu(B_TRANSLATE("View"));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("100% scale"), new BMessage(kViewScale1x), '1'));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("200% scale"), new BMessage(kViewScale2x), '2'));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("300% scale"), new BMessage(kViewScale3x), '3'));
+ menu->AddSeparatorItem();
+- fFilteringMenu = new BMenu("Filtering");
+- fFilteringMenuItem = new BMenuItem("Bilinear", new BMessage(kViewFiltering));
++ fFilteringMenu = new BMenu(B_TRANSLATE("Filtering"));
++ fFilteringMenuItem = new BMenuItem(B_TRANSLATE("Bilinear"), new BMessage(kViewFiltering));
+ fFilteringMenu->AddItem(fFilteringMenuItem);
+- fXBRFilteringMenuItem = new BMenuItem("XBR", new BMessage(kViewXBRFiltering));
++ fXBRFilteringMenuItem = new BMenuItem(B_TRANSLATE("XBR"), new BMessage(kViewXBRFiltering));
+ fFilteringMenu->AddItem(fXBRFilteringMenuItem);
+ menu->AddItem(fFilteringMenu);
+- fSmartBorderScaleMenuItem = new BMenuItem("Smart border scale", new BMessage(kViewSmartBorder));
++ fSmartBorderScaleMenuItem = new BMenuItem(B_TRANSLATE("Smart border scale"), new BMessage(kViewSmartBorder));
+ menu->AddItem(fSmartBorderScaleMenuItem);
+ menu->AddSeparatorItem();
+- fVirtualKeyboardMenuItem = new BMenuItem("Virtual keyboard", new BMessage(kHelpKeyboardLayout));
++ fVirtualKeyboardMenuItem = new BMenuItem(B_TRANSLATE("Virtual keyboard"), new BMessage(kHelpKeyboardLayout));
+ menu->AddItem(fVirtualKeyboardMenuItem);
+- menu->AddItem(new BMenuItem("OSD keyboard", new BMessage(kViewOnScreenKeyboard), 'K'));
+- menu->AddItem(new BMenuItem("OSD menu", new BMessage(kViewOnScreenMenu)));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("OSD keyboard"), new BMessage(kViewOnScreenKeyboard), 'K'));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("OSD menu"), new BMessage(kViewOnScreenMenu)));
+ menu->AddSeparatorItem();
+- menu->AddItem(new BMenuItem("Full screen", new BMessage(kViewFullScreen), B_ENTER));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Full screen"), new BMessage(kViewFullScreen), B_ENTER));
+ fMenuBar->AddItem(menu);
+- menu = new BMenu("Device");
+- menu->AddItem(new BMenuItem("Start / Stop tape", new BMessage(kDeviceStartStopTape)));
+- fFastTapeMenuItem = new BMenuItem("Tape fast", new BMessage(kDeviceFastTape));
++ menu = new BMenu(B_TRANSLATE("Device"));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Start / Stop tape"), new BMessage(kDeviceStartStopTape)));
++ fFastTapeMenuItem = new BMenuItem(B_TRANSLATE("Tape fast"), new BMessage(kDeviceFastTape));
+ menu->AddItem(fFastTapeMenuItem);
+ menu->AddSeparatorItem();
+- fBetaDiskMenu = new BMenu("Beta disk drive");
++ fBetaDiskMenu = new BMenu(B_TRANSLATE("Beta disk drive"));
+ fBetaDiskMenu->AddItem(new BMenuItem("A", new BMessage(kDeviceBetaDiskA)));
+ fBetaDiskMenu->AddItem(new BMenuItem("B", new BMessage(kDeviceBetaDiskB)));
+ fBetaDiskMenu->AddItem(new BMenuItem("C", new BMessage(kDeviceBetaDiskC)));
+ fBetaDiskMenu->AddItem(new BMenuItem("D", new BMessage(kDeviceBetaDiskD)));
+ menu->AddItem(fBetaDiskMenu);
+ menu->AddSeparatorItem();
+- fSoundChipMenu = new BMenu("Sound chip");
+- fSoundChipMenu->AddItem(new BMenuItem("AY-3-8910", new BMessage(kDeviceSoundChipAY)));
+- fSoundChipMenu->AddItem(new BMenuItem("YM2149F", new BMessage(kDeviceSoundChipYM)));
++ fSoundChipMenu = new BMenu(B_TRANSLATE("Sound chip"));
++ fSoundChipMenu->AddItem(new BMenuItem(B_TRANSLATE("AY-3-8910"), new BMessage(kDeviceSoundChipAY)));
++ fSoundChipMenu->AddItem(new BMenuItem(B_TRANSLATE("YM2149F"), new BMessage(kDeviceSoundChipYM)));
+ menu->AddItem(fSoundChipMenu);
+- fAYStereoMenu = new BMenu("AY Stereo");
++ fAYStereoMenu = new BMenu(B_TRANSLATE("AY Stereo"));
+ fAYStereoMenu->AddItem(new BMenuItem("ABC", new BMessage(kDeviceSoundChipStereoABC)));
+ fAYStereoMenu->AddItem(new BMenuItem("ACB", new BMessage(kDeviceSoundChipStereoACB)));
+ fAYStereoMenu->AddItem(new BMenuItem("BAC", new BMessage(kDeviceSoundChipStereoBAC)));
+ fAYStereoMenu->AddItem(new BMenuItem("BCA", new BMessage(kDeviceSoundChipStereoBCA)));
+ fAYStereoMenu->AddItem(new BMenuItem("CAB", new BMessage(kDeviceSoundChipStereoCAB)));
+ fAYStereoMenu->AddItem(new BMenuItem("CBA", new BMessage(kDeviceSoundChipStereoCBA)));
+- fAYStereoMenu->AddItem(new BMenuItem("Mono", new BMessage(kDeviceSoundChipStereoMono)));
++ fAYStereoMenu->AddItem(new BMenuItem(B_TRANSLATE("Mono"), new BMessage(kDeviceSoundChipStereoMono)));
+ fAYStereoMenu->SetRadioMode(true);
+ menu->AddItem(fAYStereoMenu);
+- fSoundVolumeMenu = new BMenu("Volume");
++ fSoundVolumeMenu = new BMenu(B_TRANSLATE("Volume"));
+ for (int volume = 0; volume <= 10; volume++) {
+ BMessage *message = new BMessage(kDeviceSoundVolume);
+ message->AddInt32("volume", volume);
+ BString title;
+ if (volume == 0)
+- title = "Mute";
++ title = B_TRANSLATE("Mute");
+ else
+ title << (volume * 10) << " %";
+ fSoundVolumeMenu->AddItem(new BMenuItem(title, message));
+@@ -193,32 +196,34 @@ HaikuPlatformWindow::HaikuPlatformWindow(BRect frame, int w, int h, const char*
+ fSoundVolumeMenu->SetRadioMode(true);
+ menu->AddItem(fSoundVolumeMenu);
+ menu->AddSeparatorItem();
+- fJoystickMenu = new BMenu("Joystick");
+- fJoystickMenu->AddItem(new BMenuItem("Cursor", new BMessage(kDeviceJoystickCursor)));
+- fJoystickMenu->AddItem(new BMenuItem("Cursor + Enter", new BMessage(kDeviceJoystickCursorEnter)));
+- fJoystickMenu->AddItem(new BMenuItem("Kempston", new BMessage(kDeviceJoystickKempston)));
+- fJoystickMenu->AddItem(new BMenuItem("Sinclair 2", new BMessage(kDeviceJoystickSinclair2)));
+- fJoystickMenu->AddItem(new BMenuItem("QAOPM", new BMessage(kDeviceJoystickQAOPM)));
+- fJoystickMenu->AddItem(new BMenuItem("QAOP + Space", new BMessage(kDeviceJoystickQAOPSpace)));
++ fJoystickMenu = new BMenu(B_TRANSLATE("Joystick"));
++ fJoystickMenu->AddItem(new BMenuItem(B_TRANSLATE("Cursor"), new BMessage(kDeviceJoystickCursor)));
++ fJoystickMenu->AddItem(new BMenuItem(B_TRANSLATE("Cursor + Enter"), new BMessage(kDeviceJoystickCursorEnter)));
++ fJoystickMenu->AddItem(new BMenuItem(B_TRANSLATE("Kempston"), new BMessage(kDeviceJoystickKempston)));
++ fJoystickMenu->AddItem(new BMenuItem(B_TRANSLATE("Sinclair 2"), new BMessage(kDeviceJoystickSinclair2)));
++ fJoystickMenu->AddItem(new BMenuItem(B_TRANSLATE("QAOPM"), new BMessage(kDeviceJoystickQAOPM)));
++ fJoystickMenu->AddItem(new BMenuItem(B_TRANSLATE("QAOP + Space"), new BMessage(kDeviceJoystickQAOPSpace)));
+ fJoystickMenu->SetRadioMode(true);
+ menu->AddItem(fJoystickMenu);
+ menu->AddSeparatorItem();
+- fKempstonMouseGrabMenuItem = new BMenuItem("Kempson mouse grab", new BMessage(kDeviceKempsonMouse), 'G');
++ fKempstonMouseGrabMenuItem = new BMenuItem(B_TRANSLATE("Kempson mouse grab"), new BMessage(kDeviceKempsonMouse), 'G');
+ menu->AddItem(fKempstonMouseGrabMenuItem);
+ menu->AddSeparatorItem();
+- f48kModeMenuItem = new BMenuItem("Mode 48k", new BMessage(kDeviceMode48k), 'M');
++ f48kModeMenuItem = new BMenuItem(B_TRANSLATE("Mode 48k"), new BMessage(kDeviceMode48k), 'M');
+ menu->AddItem(f48kModeMenuItem);
+ menu->AddSeparatorItem();
+- fPauseMenuItem = new BMenuItem("Pause", new BMessage(kDevicePause), 'P');
++ fPauseMenuItem = new BMenuItem(B_TRANSLATE("Pause"), new BMessage(kDevicePause), 'P');
+ menu->AddItem(fPauseMenuItem);
+- fResetToServiceROMMenuItem = new BMenuItem("Reset to service ROM", new BMessage(kDeviceResetToServiceROM));
++ fResetToServiceROMMenuItem = new BMenuItem(B_TRANSLATE("Reset to service ROM"), new BMessage(kDeviceResetToServiceROM));
+ menu->AddItem(fResetToServiceROMMenuItem);
+- menu->AddItem(new BMenuItem("Reset", new BMessage(kDeviceReset), 'R'));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Reset"), new BMessage(kDeviceReset), 'R'));
+ fMenuBar->AddItem(menu);
+- menu = new BMenu("Help");
+- menu->AddItem(new BMenuItem("Register filetypes", new BMessage(kHelpRegisterMime)));
++ menu = new BMenu(B_TRANSLATE("Help"));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Register filetypes"), new BMessage(kHelpRegisterMime)));
++ menu->AddSeparatorItem();
++ menu->AddItem(new BMenuItem(B_TRANSLATE("Visit homepage"), new BMessage(kHelpOpenHomePage)));
+ menu->AddSeparatorItem();
+- menu->AddItem(new BMenuItem("About", new BMessage(B_ABOUT_REQUESTED)));
++ menu->AddItem(new BMenuItem(B_TRANSLATE("About"), new BMessage(B_ABOUT_REQUESTED)));
+ fMenuBar->AddItem(menu);
+
+ AddShortcut('F', B_COMMAND_KEY, new BMessage(kViewFullScreen));
+@@ -230,15 +235,15 @@ HaikuPlatformWindow::HaikuPlatformWindow(BRect frame, int w, int h, const char*
+ BFont font(be_plain_font);
+ font.SetSize(ceilf(font.Size() * 0.75));
+
+- fStatusMode = new BStringView("status", "128k");
++ fStatusMode = new BStringView("status", B_TRANSLATE("128k"));
+ fStatusMode->SetFont(&font, B_FONT_SIZE);
+ fStatusMode->SetAlignment(B_ALIGN_LEFT);
+
+- fStatusDisk = new BStringView("disk status", "[A] B C D");
++ fStatusDisk = new BStringView("disk status", "[A] b c d");
+ fStatusDisk->SetFont(&font, B_FONT_SIZE);
+ fStatusDisk->SetAlignment(B_ALIGN_LEFT);
+
+- fStatusJoystick = new BStringView("joystick status", "Cursor");
++ fStatusJoystick = new BStringView("joystick status", B_TRANSLATE("Cursor"));
+ fStatusJoystick->SetFont(&font, B_FONT_SIZE);
+ fStatusJoystick->SetAlignment(B_ALIGN_LEFT);
+
+@@ -246,7 +251,7 @@ HaikuPlatformWindow::HaikuPlatformWindow(BRect frame, int w, int h, const char*
+ fStatusSound->SetFont(&font, B_FONT_SIZE);
+ fStatusSound->SetAlignment(B_ALIGN_LEFT);
+
+- fStatusInfo = new BStringView("status info", "Ready");
++ fStatusInfo = new BStringView("status info", B_TRANSLATE("Ready"));
+ fStatusInfo->SetFont(&font, B_FONT_SIZE);
+ fStatusInfo->SetAlignment(B_ALIGN_LEFT);
+
+@@ -382,9 +387,9 @@ HaikuPlatformWindow::UpdateMenus()
+
+ // update status line
+ if (op_mode_48k && *op_mode_48k)
+- fStatusMode->SetText("48k");
++ fStatusMode->SetText(B_TRANSLATE("48k"));
+ else
+- fStatusMode->SetText("128k");
++ fStatusMode->SetText(B_TRANSLATE("128k"));
+
+ if (drive == D_A)fStatusDisk->SetText("[A] b c d");
+ if (drive == D_B)fStatusDisk->SetText("a [B] c d");
+@@ -403,8 +408,9 @@ HaikuPlatformWindow::UpdateMenus()
+ soundStatus << "ABC";
+
+ BString volumeTxt;
+- volumeTxt << " " << (OpVolume() * 10) << "%";
+- soundStatus += OpVolume() == 0 ? " Mute" : volumeTxt;
++ volumeTxt << (OpVolume() * 10) << "%";
++ soundStatus += " ";
++ soundStatus += ((OpVolume() == 0) ? B_TRANSLATE("Mute") : volumeTxt.String());
+ fStatusSound->SetText(soundStatus);
+ }
+
+@@ -459,14 +465,14 @@ HaikuPlatformWindow::InstallMimeType(const char *_mime, const char *_icon, const
+ BMimeType mime(_mime);
+ status_t ret = mime.InitCheck();
+ if (ret != B_OK) {
+- fprintf(stderr, "Could not init native document mime type (%s): %s.\n",
++ fprintf(stderr, B_TRANSLATE("Could not init native document mime type (%s): %s.\n"),
+ _mime, strerror(ret));
+ return;
+ }
+
+ ret = mime.Install();
+ if (ret != B_OK && ret != B_FILE_EXISTS) {
+- fprintf(stderr, "Could not install native document mime type (%s): %s.\n",
++ fprintf(stderr, B_TRANSLATE("Could not install native document mime type (%s): %s.\n"),
+ _mime, strerror(ret));
+ return;
+ }
+@@ -490,12 +496,12 @@ HaikuPlatformWindow::InstallMimeType(const char *_mime, const char *_icon, const
+ const void* iconData = resources->LoadResource('VICN', _icon, &size);
+ if (iconData != NULL && size > 0) {
+ if (mime.SetIcon(reinterpret_cast(iconData), size) != B_OK)
+- fprintf(stderr, "Could not set vector icon of mime type.\n");
++ fprintf(stderr, B_TRANSLATE("Could not set vector icon of mime type.\n"));
+ } else {
+- fprintf(stderr, "Could not find icon in app resources (data: %p, size: %ld).\n", iconData, size);
++ fprintf(stderr, B_TRANSLATE("Could not find icon in app resources (data: %p, size: %ld).\n"), iconData, size);
+ }
+ } else
+- fprintf(stderr, "Could not find app resources.\n");
++ fprintf(stderr, B_TRANSLATE("Could not find app resources.\n"));
+ }
+
+ void
+@@ -510,7 +516,7 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ if (fStateInfoTimer > 0) {
+ fStateInfoTimer--;
+ if (fStateInfoTimer == 0)
+- SetStatusInfo("Ready");
++ SetStatusInfo(B_TRANSLATE("Ready"));
+ }
+ break;
+ }
+@@ -518,7 +524,7 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ {
+ if (!fOpenPanel) {
+ fOpenPanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, 0, true, NULL, NULL, true, true);
+- fOpenPanel->Window()->SetTitle("Open file...");
++ fOpenPanel->Window()->SetTitle(B_TRANSLATE("Open file" B_UTF8_ELLIPSIS));
+ fOpenPanel->SetTarget(this);
+ }
+ Handler()->VideoPaused(true);
+@@ -541,10 +547,10 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ if(loadState)
+ loadState->Change();
+ if (*loadState) {
+- SetStatusInfo("Quick load OK", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Quick load OK"), STATUS_TIME_DEFAULT);
+ fQuickSaveMenuItem->SetEnabled(true);
+ } else
+- SetStatusInfo("Quick load FAILED", STATUS_TIME_DEFAULT, B_FAILURE_COLOR);
++ SetStatusInfo(B_TRANSLATE("Quick load FAILED"), STATUS_TIME_DEFAULT, B_FAILURE_COLOR);
+ break;
+ }
+ case kFileQuickSave:
+@@ -557,9 +563,9 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ Handler()->VideoPaused(false);
+ }
+ if (*saveState)
+- SetStatusInfo("Quick save OK", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Quick save OK"), STATUS_TIME_DEFAULT);
+ else
+- SetStatusInfo("Quick save FAILED", STATUS_TIME_DEFAULT, B_FAILURE_COLOR);
++ SetStatusInfo(B_TRANSLATE("Quick save FAILED"), STATUS_TIME_DEFAULT, B_FAILURE_COLOR);
+ break;
+ }
+ case kFileQuickSaveSlot:
+@@ -576,7 +582,7 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ {
+ if (!fSavePanel) {
+ fSavePanel = new BFilePanel(B_SAVE_PANEL, NULL, NULL, 0, true, NULL, NULL, true, true);
+- fSavePanel->Window()->SetTitle("Save SNA snapshot...");
++ fSavePanel->Window()->SetTitle(B_TRANSLATE("Save SNA snapshot" B_UTF8_ELLIPSIS));
+ fSavePanel->SetTarget(this);
+ }
+ Handler()->VideoPaused(true);
+@@ -588,7 +594,7 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ if (!fSaveScreenPanel) {
+ fSaveScreenPanel = new BFilePanel(B_SAVE_PANEL, NULL, NULL, 0, true, NULL, NULL, true, true);
+ fSaveScreenPanel->SetMessage(new BMessage(B_SAVE_SCREEN_REQUESTED));
+- fSaveScreenPanel->Window()->SetTitle("Save screenshot...");
++ fSaveScreenPanel->Window()->SetTitle(B_TRANSLATE("Save screenshot" B_UTF8_ELLIPSIS));
+ fSaveScreenPanel->SetTarget(this);
+ }
+ Handler()->VideoPaused(true);
+@@ -598,9 +604,9 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ case kFileAutoPlay:
+ {
+ if(UpdateBoolOption(fAutoPlayMenuItem, "auto play image", true)) {
+- SetStatusInfo("Auto launch on", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Auto launch on"), STATUS_TIME_DEFAULT);
+ } else {
+- SetStatusInfo("Auto launch off", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Auto launch off"), STATUS_TIME_DEFAULT);
+ }
+ UpdateMenus();
+ break;
+@@ -619,10 +625,10 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ BString text;
+ bool status = Handler()->OnOpenFile(path.Path());
+ if (status) {
+- text << "File was successfully opened";
++ text << B_TRANSLATE("File was successfully opened");
+ fQuickSaveMenuItem->SetEnabled(true);
+ } else
+- text << "Could not open file";
++ text << B_TRANSLATE("Could not open file");
+
+ SetStatusInfo(text.String(), STATUS_TIME_DEFAULT, status ? B_PANEL_TEXT_COLOR : B_FAILURE_COLOR);
+ }
+@@ -641,9 +647,9 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ name += ".sna";
+ pathname.Append(name);
+ if(Handler()->OnSaveFile(pathname.Path()))
+- SetStatusInfo("File save OK", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("File save OK"), STATUS_TIME_DEFAULT);
+ else
+- SetStatusInfo("File save FAILED", STATUS_TIME_DEFAULT, B_FAILURE_COLOR);
++ SetStatusInfo(B_TRANSLATE("File save FAILED"), STATUS_TIME_DEFAULT, B_FAILURE_COLOR);
+ }
+ }
+ break;
+@@ -661,9 +667,9 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ name += ".png";
+ pathname.Append(name);
+ if (Handler()->OnSaveFile(pathname.Path()))
+- SetStatusInfo("Screenshot save OK", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Screenshot save OK"), STATUS_TIME_DEFAULT);
+ else
+- SetStatusInfo("Screenshot save FAILED", STATUS_TIME_DEFAULT, B_FAILURE_COLOR);
++ SetStatusInfo(B_TRANSLATE("Screenshot save FAILED"), STATUS_TIME_DEFAULT, B_FAILURE_COLOR);
+ }
+ }
+ break;
+@@ -699,7 +705,7 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ fFiltering = !fFiltering;
+ fView->EnableBilinear(fFiltering);
+ op_scale_bilinear.Set(fFiltering);
+- SetStatusInfo(fFiltering ? "Filtering enabled" : "Filtering disabled", STATUS_TIME_DEFAULT);
++ SetStatusInfo(fFiltering ? B_TRANSLATE("Filtering enabled") : B_TRANSLATE("Filtering disabled"), STATUS_TIME_DEFAULT);
+ UpdateMenus();
+ break;
+ }
+@@ -708,7 +714,7 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ fXBRFiltering = !fXBRFiltering;
+ fView->EnableXBR(fXBRFiltering);
+ op_xbr_scale.Set(fXBRFiltering);
+- SetStatusInfo(fXBRFiltering ? "XBR Filtering enabled" : "XBR Filtering disabled", STATUS_TIME_DEFAULT);
++ SetStatusInfo(fXBRFiltering ? B_TRANSLATE("XBR Filtering enabled") : B_TRANSLATE("XBR Filtering disabled"), STATUS_TIME_DEFAULT);
+ UpdateMenus();
+ break;
+ }
+@@ -716,7 +722,7 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ {
+ op_smart_border_disabled.Set(!op_smart_border_disabled);
+ fView->EnableSmartBorder(!op_smart_border_disabled);
+- SetStatusInfo(op_smart_border_disabled ? "Smart border disabled" : "Smart border enabled", STATUS_TIME_DEFAULT);
++ SetStatusInfo(op_smart_border_disabled ? B_TRANSLATE("Smart border disabled") : B_TRANSLATE("Smart border enabled"), STATUS_TIME_DEFAULT);
+ UpdateMenus();
+ break;
+ }
+@@ -737,16 +743,16 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ switch(Handler()->OnAction(A_TAPE_TOGGLE))
+ {
+ case AR_TAPE_STARTED:
+- SetStatusInfo("Tape started", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Tape started"), STATUS_TIME_DEFAULT);
+ break;
+ case AR_TAPE_STOPPED:
+- SetStatusInfo("Tape stopped", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Tape stopped"), STATUS_TIME_DEFAULT);
+ break;
+ case AR_TAPE_NOT_INSERTED:
+- SetStatusInfo("Tape not inserted", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Tape not inserted"), STATUS_TIME_DEFAULT);
+ break;
+ default:
+- SetStatusInfo("Ready");
++ SetStatusInfo(B_TRANSLATE("Ready"));
+ break;
+ }
+ break;
+@@ -757,7 +763,7 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ eOption* op_tape_fast = eOption::Find("fast tape");
+ SAFE_CALL(op_tape_fast)->Change();
+ bool tape_fast = op_tape_fast && *op_tape_fast;
+- SetStatusInfo(tape_fast ? "Fast tape on" : "Fast tape off", STATUS_TIME_DEFAULT);
++ SetStatusInfo(tape_fast ? B_TRANSLATE("Fast tape on") : B_TRANSLATE("Fast tape off"), STATUS_TIME_DEFAULT);
+ UpdateMenus();
+ break;
+ }
+@@ -914,7 +920,7 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ {
+ fKempsonMouseGrab = !fKempsonMouseGrab;
+ fView->EnableMouseGrab(fKempsonMouseGrab);
+- SetStatusInfo(fKempsonMouseGrab ? "Mouse grabbed (Alt+G)" : "Ready");
++ SetStatusInfo(fKempsonMouseGrab ? B_TRANSLATE("Mouse grabbed (Alt+G)") : B_TRANSLATE("Ready"));
+ UpdateMenus();
+ UpdateCursor();
+ break;
+@@ -924,30 +930,30 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ bool marked = fPauseMenuItem->IsMarked();
+ fPauseMenuItem->SetMarked(!marked);
+ Handler()->VideoPaused(!marked);
+- SetStatusInfo(marked ? "Ready" : "Paused");
++ SetStatusInfo(marked ? B_TRANSLATE("Ready") : B_TRANSLATE("Paused"));
+ break;
+ }
+ case kDeviceReset:
+ {
+- SetStatusInfo("Reset", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Reset"), STATUS_TIME_DEFAULT);
+ Handler()->OnAction(A_RESET);
+ break;
+ }
+ case kDeviceMode48k:
+ {
+ if (UpdateBoolOption(f48kModeMenuItem, "mode 48k", true))
+- SetStatusInfo("48k mode enabled", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("48k mode enabled"), STATUS_TIME_DEFAULT);
+ else
+- SetStatusInfo("128k mode enabled", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("128k mode enabled"), STATUS_TIME_DEFAULT);
+ UpdateMenus();
+ break;
+ }
+ case kDeviceResetToServiceROM:
+ {
+ if (UpdateBoolOption(fResetToServiceROMMenuItem, "reset to service rom", true))
+- SetStatusInfo("Reset to service ROM", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Reset to service ROM"), STATUS_TIME_DEFAULT);
+ else
+- SetStatusInfo("Reset to usual ROM", STATUS_TIME_DEFAULT);
++ SetStatusInfo(B_TRANSLATE("Reset to usual ROM"), STATUS_TIME_DEFAULT);
+ break;
+ }
+ case kHelpKeyboardLayout:
+@@ -980,14 +986,22 @@ HaikuPlatformWindow::MessageReceived(BMessage *message)
+ InstallMimeType("application/x-spectrum-scl", "disk_icon", "TR-DOS floppy disk image (SCL)", "scl");
+ InstallMimeType("application/x-spectrum-tap", "tape_icon", "ZX-Spectrum emulator tape data (TAP)", "tap");
+ InstallMimeType("application/x-spectrum-tzx", "tape_icon", "ZX-Spectrum emulator tape data (TZX)", "tzx");
+- BAlert *alert = new BAlert("Register filetypes", "Filetypes registered!", "OK");
++ BAlert *alert = new BAlert(B_TRANSLATE("Register filetypes"), B_TRANSLATE("Filetypes registered!"), B_TRANSLATE("OK"));
+ alert->Go(NULL);
+ break;
+ }
++ case kHelpOpenHomePage:
++ {
++ entry_ref ref;
++ get_ref_for_path("/bin/open", &ref);
++ const char* args[] = { "/bin/open", "https://bitbucket.org/djdron/unrealspeccyp", NULL };
++ be_roster->Launch(&ref, 2, args);
++ break;
++ }
+ case B_ABOUT_REQUESTED:
+ {
+- BAboutWindow* wind = new BAboutWindow("Unreal Speccy Portable", "application/x-vnd.unreal-speccy-portable");
+- const char *backendCopyrights[]={"2021 Haiku UI by Gerasim Troeglazov (3dEyes**)\n", NULL};
++ BAboutWindow* wind = new BAboutWindow("Unreal Speccy Portable", APP_SIGNATURE);
++ const char *backendCopyrights[]={"2021-2023 Haiku UI by Gerasim Troeglazov (3dEyes**)\n", NULL};
+ wind->AddCopyright(2022, "SMT, Dexus, Alone Coder, deathsoft, djdron, scor.", (const char**)&backendCopyrights);
+ wind->SetVersion("0.0.86.18");
+ wind->AddDescription("Portable ZX Spectrum emulator.");
+diff --git a/platform/haiku/haiku_window.h b/platform/haiku/haiku_window.h
+index ef6b679..8394024 100644
+--- a/platform/haiku/haiku_window.h
++++ b/platform/haiku/haiku_window.h
+@@ -25,6 +25,7 @@ along with this program. If not, see .
+ #include
+ #include
+ #include
++#include
+ #include
+ #include
+ #include
+@@ -81,6 +82,7 @@ const uint32 kDeviceBetaDiskC = 'BD_C';
+ const uint32 kDeviceBetaDiskD = 'BD_D';
+ const uint32 kDeviceKempsonMouse = 'KMOU';
+ const uint32 kHelpRegisterMime = 'RMIM';
++const uint32 kHelpOpenHomePage = 'HOME';
+ const uint32 kPulseEvent = 'TIME';
+ const uint32 B_SAVE_SCREEN_REQUESTED = 'SSRQ';
+
+diff --git a/platform/haiku/locales/en.catkeys b/platform/haiku/locales/en.catkeys
+new file mode 100644
+index 0000000..910caeb
+--- /dev/null
++++ b/platform/haiku/locales/en.catkeys
+@@ -0,0 +1,98 @@
++1 English application/x-vnd.unreal-speccy-portable 2972438328
++Could not find app resources.\n USPWindow Could not find app resources.\n
++Smart border enabled USPWindow Smart border enabled
++QAOPM USPWindow QAOPM
++Cancel USPWebWindow Cancel
++Auto launch on USPWindow Auto launch on
++Could not find icon in app resources (data: %p, size: %ld).\n USPWindow Could not find icon in app resources (data: %p, size: %ld).\n
++OK USPWindow OK
++Quick load FAILED USPWindow Quick load FAILED
++Register filetypes USPWindow Register filetypes
++Ready USPWindow Ready
++Paused USPWindow Paused
++Filetypes registered! USPWindow Filetypes registered!
++Open from web… USPWindow Open from web…
++Volume USPWindow Volume
++Tape started USPWindow Tape started
++Fast tape off USPWindow Fast tape off
++300% scale USPWindow 300% scale
++48k mode enabled USPWindow 48k mode enabled
++XBR Filtering disabled USPWindow XBR Filtering disabled
++QAOP + Space USPWindow QAOP + Space
++48k USPWindow 48k
++Visit homepage USPWindow Visit homepage
++128k mode enabled USPWindow 128k mode enabled
++200% scale USPWindow 200% scale
++Keyboard layout USPKeyboardWindow Keyboard layout
++items USPWebWindow items
++About USPWindow About
++Save… USPWindow Save…
++Save slot USPWindow Save slot
++Could not set vector icon of mime type.\n USPWindow Could not set vector icon of mime type.\n
++Smart border scale USPWindow Smart border scale
++100% scale USPWindow 100% scale
++Filtering USPWindow Filtering
++Open file from web… USPWebWindow Open file from web…
++View USPWindow View
++Mute USPWindow Mute
++Help USPWindow Help
++Cursor + Enter USPWindow Cursor + Enter
++File save FAILED USPWindow File save FAILED
++AY Stereo USPWindow AY Stereo
++Save SNA snapshot… USPWindow Save SNA snapshot…
++AY-3-8910 USPWindow AY-3-8910
++File USPWebWindow File
++Cursor USPWindow Cursor
++Full screen USPWindow Full screen
++Quit USPWindow Quit
++Fast tape on USPWindow Fast tape on
++Quick load USPWindow Quick load
++Sinclair 2 USPWindow Sinclair 2
++File USPWindow File
++Mode 48k USPWindow Mode 48k
++Screenshot save FAILED USPWindow Screenshot save FAILED
++Open file… USPWindow Open file…
++128k USPWindow 128k
++File was successfully opened USPWindow File was successfully opened
++XBR USPWindow XBR
++Auto launch programs USPWindow Auto launch programs
++Joystick USPWindow Joystick
++Save screenshot… USPWindow Save screenshot…
++Filtering disabled USPWindow Filtering disabled
++Could not open file USPWindow Could not open file
++Kempson mouse grab USPWindow Kempson mouse grab
++XBR Filtering enabled USPWindow XBR Filtering enabled
++Reset to service ROM USPWindow Reset to service ROM
++OSD keyboard USPWindow OSD keyboard
++Open download folder USPWebWindow Open download folder
++Virtual keyboard USPWindow Virtual keyboard
++YM2149F USPWindow YM2149F
++Bilinear USPWindow Bilinear
++Screenshot save OK USPWindow Screenshot save OK
++Tape not inserted USPWindow Tape not inserted
++Tape stopped USPWindow Tape stopped
++Download file USPWebWindow Download file
++Filtering enabled USPWindow Filtering enabled
++Quick load OK USPWindow Quick load OK
++Quick save FAILED USPWindow Quick save FAILED
++Quick save USPWindow Quick save
++Tape fast USPWindow Tape fast
++Start / Stop tape USPWindow Start / Stop tape
++Beta disk drive USPWindow Beta disk drive
++Mono USPWindow Mono
++Open USPWebWindow Open
++Quick save OK USPWindow Quick save OK
++Open… USPWindow Open…
++Could not init native document mime type (%s): %s.\n USPWindow Could not init native document mime type (%s): %s.\n
++Reset USPWindow Reset
++Device USPWindow Device
++File save OK USPWindow File save OK
++Sound chip USPWindow Sound chip
++Pause USPWindow Pause
++Mouse grabbed (Alt+G) USPWindow Mouse grabbed (Alt+G)
++Kempston USPWindow Kempston
++Could not install native document mime type (%s): %s.\n USPWindow Could not install native document mime type (%s): %s.\n
++OSD menu USPWindow OSD menu
++Smart border disabled USPWindow Smart border disabled
++Reset to usual ROM USPWindow Reset to usual ROM
++Auto launch off USPWindow Auto launch off
+diff --git a/platform/haiku/locales/ru.catkeys b/platform/haiku/locales/ru.catkeys
+new file mode 100755
+index 0000000..5cbd2cc
+--- /dev/null
++++ b/platform/haiku/locales/ru.catkeys
+@@ -0,0 +1,98 @@
++1 Russian application/x-vnd.unreal-speccy-portable 2972438328
++100% scale USPWindow Масштаб 100%
++128k USPWindow 128кб
++128k mode enabled USPWindow 128кб режим включен
++200% scale USPWindow Масштаб 200%
++300% scale USPWindow Масштаб 300%
++48k USPWindow 48кб
++48k mode enabled USPWindow 48кб режим включен
++About USPWindow О программе
++Auto launch off USPWindow Автозапуск выключен
++Auto launch on USPWindow Автозапуск включен
++Auto launch programs USPWindow Автозапуск программ
++AY Stereo USPWindow AY Стерео
++AY-3-8910 USPWindow AY-3-8910
++Beta disk drive USPWindow Дисковод
++Bilinear USPWindow Билинейное
++Could not find app resources.\n USPWindow Не могу найти файлы ресурсов программы.\n
++Could not find icon in app resources (data: %p, size: %ld).\n USPWindow Иконка не найдена в ресурсах приложения (data: %p, size: %ld).\n
++Could not init native document mime type (%s): %s.\n USPWindow Не могу инициализировать mime-тип(%s): %s.\n
++Could not install native document mime type (%s): %s.\n USPWindow Не могу установить mime-тип (%s): %s.\n
++Could not open file USPWindow Ошибка открытия файла
++Could not set vector icon of mime type.\n USPWindow Не могу установить иконку для mime-типа.\n
++Cursor USPWindow Курсор
++Cursor + Enter USPWindow Курсор + Enter
++Device USPWindow Периферия
++Fast tape off USPWindow Быстрая загрузка с ленты выключена
++Fast tape on USPWindow Быстрая загрузка с ленты включена
++File USPWindow Файл
++File save FAILED USPWindow Ошибка сохранения файла
++File save OK USPWindow Сохранение выполнено
++File was successfully opened USPWindow Файл успешно загружен
++Filetypes registered! USPWindow Файловые типы зарегистрированы!
++Filtering USPWindow Сглаживание
++Filtering disabled USPWindow Сглаживание выключено
++Filtering enabled USPWindow Сглаживание включено
++Full screen USPWindow Полноэкранный режим
++Help USPWindow Справка
++Joystick USPWindow Джойстик
++Kempson mouse grab USPWindow Кемпстон мышь (захват)
++Kempston USPWindow Кемпстон
++Mode 48k USPWindow Режим 48кб
++Mono USPWindow Моно
++Mouse grabbed (Alt+G) USPWindow Мышь захвачена (Alt+G)
++Mute USPWindow Без звука
++OK USPWindow ОК
++Open file… USPWindow Открыть файл…
++Open from web… USPWindow Открыть из интернета…
++Open… USPWindow Открыть…
++OSD keyboard USPWindow OSD клавиатура
++OSD menu USPWindow OSD меню
++Pause USPWindow Пауза
++Paused USPWindow Пауза
++QAOP + Space USPWindow QAOP + Пробел
++QAOPM USPWindow QAOPM
++Quick load USPWindow Быстрая загрузка
++Quick load FAILED USPWindow Ошибка быстрой загрузки
++Quick load OK USPWindow Быстрая загрузка выполнена
++Quick save USPWindow Быстрое сохранение
++Quick save FAILED USPWindow Ошибка быстрого сохранения
++Quick save OK USPWindow Быстрое сохранение выполнено
++Quit USPWindow Выход
++Ready USPWindow Готов
++Register filetypes USPWindow Зарегистрировать файловые типы
++Reset USPWindow Сброс
++Reset to service ROM USPWindow Сброс в сервисное ПЗУ
++Reset to usual ROM USPWindow Сброс в стандартное ПЗУ
++Save screenshot… USPWindow Сохранить снимок экрана…
++Save slot USPWindow Сохранить в слот
++Save SNA snapshot… USPWindow Сохранить SNA снапшот…
++Save… USPWindow Сохранить…
++Screenshot save FAILED USPWindow Ошибка сохранения снимка экрана
++Screenshot save OK USPWindow Снимок экрана сохранён
++Sinclair 2 USPWindow Синклер 2
++Smart border disabled USPWindow Умное масштабирование выключено
++Smart border enabled USPWindow Умное масштабирование включено
++Smart border scale USPWindow Умное масштабирование бордюра
++Sound chip USPWindow Звуковой чип
++Start / Stop tape USPWindow Старт / Стоп загрузки с ленты
++Tape fast USPWindow Быстрая загрузка с ленты
++Tape not inserted USPWindow Лента отсутсвует
++Tape started USPWindow Лента включена
++Tape stopped USPWindow Лента остановлена
++View USPWindow Вид
++Virtual keyboard USPWindow Виртуальная клавиатура
++Visit homepage USPWindow Открыть сайт проекта
++Volume USPWindow Громкость
++XBR USPWindow XBR
++XBR Filtering disabled USPWindow XBR сглаживание выключено
++XBR Filtering enabled USPWindow XBR сглаживание включено
++YM2149F USPWindow YM2149F
++Cancel USPWebWindow Отмена
++Download file USPWebWindow Загрузить файл
++File USPWebWindow Файл
++items USPWebWindow объектов
++Open USPWebWindow Открыть
++Open download folder USPWebWindow Открыть каталог с загрузками
++Open file from web… USPWebWindow Открыть файл из интернета…
++Keyboard layout USPKeyboardWindow Виртуальная клавиатура
+--
+2.37.3
diff --git a/app-emulation/unreal_speccy_portable/unreal_speccy_portable-0.0.86.18.recipe b/app-emulation/unreal_speccy_portable/unreal_speccy_portable-0.0.86.18.recipe
index 12f8c6de9..0a21a9d15 100644
--- a/app-emulation/unreal_speccy_portable/unreal_speccy_portable-0.0.86.18.recipe
+++ b/app-emulation/unreal_speccy_portable/unreal_speccy_portable-0.0.86.18.recipe
@@ -5,7 +5,7 @@ Supported formats: sna, z80, szx, rzx, tap, tzx, csw, trd, scl, fdi, td0, udi, z
HOMEPAGE="https://bitbucket.org/djdron/unrealspeccyp"
COPYRIGHT="2014-2022 SMT, Dexus, Alone Coder, deathsoft, djdron, scor, 3dEyes"
LICENSE="GNU GPL v3"
-REVISION="1"
+REVISION="2"
SOURCE_URI="https://github.com/djdron/UnrealSpeccyP/archive/refs/tags/v$portVersion.tar.gz"
CHECKSUM_SHA256="bfab2463a7eb8e720770eaea9bc50cdc70bbbda190af2ff6b5bd8a970b9fa8c0"
SOURCE_DIR="UnrealSpeccyP-$portVersion"
@@ -48,6 +48,13 @@ BUILD()
cd build/cmake/build
cmake .. -DCMAKE_BUILD_TYPE=Release -DUSE_HAIKU=ON
make $jobArgs
+
+ signature="application/x-vnd.unreal-speccy-portable"
+ for file in $sourceDir/platform/haiku/locales/*.catkeys
+ do
+ filename=$(basename "$file")
+ linkcatkeys -o unreal_speccy_portable -s $signature -tr -l ${filename%.*} $file
+ done
}
INSTALL()