瀏覽代碼

Menu moved to language file

Arthur Yefimov 3 年之前
父節點
當前提交
4db68878e8
共有 3 個文件被更改,包括 218 次插入17 次删除
  1. 79 0
      Data/Texts/en.dat
  2. 47 8
      src/FoStrings.Mod
  3. 92 9
      src/FreeOberon.Mod

+ 79 - 0
Data/Texts/en.dat

@@ -188,3 +188,82 @@
 244 "cyclic type definition not allowed"
 244 "cyclic type definition not allowed"
 265 "unsupported string operation"
 265 "unsupported string operation"
 401 "file contains wrong module name"
 401 "file contains wrong module name"
+
+menuFile "&File"
+menuOpen "&Open"
+menuReload "&Reload"
+menuSave "&Save"
+menuSaveAs "Save &as..."
+menuSaveAll "Save a&ll"
+menuExit "E&xit"
+menuEdit "&Edit"
+menuUndo "&Undo"
+menuRedo "&Redo"
+menuCut "Cu&t"
+menuCopy "&Copy"
+menuPaste "&Paste"
+menuClear "C&lear"
+menuSelectAll "Select &All"
+menuUnselect "U&nselect"
+menuSearch "&Search"
+menuFind "&Find..."
+menuReplace "&Replace..."
+menuSearchAgain "&Search again"
+menuGoToLineNumber "&Go to line number..."
+menuFindProcedure "&Find procedure..."
+menuRun "&Run"
+menuRunDirectory "Run &Directory..."
+menuParameters "P&arameters..."
+menuCompile "&Compile"
+menuMake "&Make"
+menuMakeAndRun "Make && &Run"
+menuBuild "&Build"
+menuDebug "&Debug"
+menuOutput "&Output"
+menuTools "&Tools"
+menuMessages "&Messages"
+menuCalculator "&Calculator"
+menuAsciiTable "Ascii &table"
+menuOptions "&Options"
+menuMode "Mode&..."
+menuNormalMode "Normal"
+menuCompiler "&Compiler..."
+menuMemorySizes "&Memory sizes..."
+menuLinker "&Linker..."
+menuDirectories "&Directories..."
+menuTools "&Tools..."
+menuEnvironment "&Environment"
+menuPreferences "&Preferences..."
+menuEditor "&Editor..."
+menuCodeComplete "Code&Complete..."
+menuCodeTemplates "Code&Templates..."
+menuDesktop "&Desktop..."
+menuKeyboardAndMouse "Keyboard && &mouse..."
+menuLearnKeys "Learn &Keys"
+menuOpenOptions "&Open..."
+menuSaveOptions "&Save"
+menuSaveOptionsAs "Save &as..."
+menuWindow "&Window"
+menuTile "&Tile"
+menuCascade "C&ascade"
+menuCloseAll "Cl&ose all"
+menuSizeMove "&Size/Move"
+menuZoom "&Zoom"
+menuNextWindow "&Next"
+menuPreviousWindow "&Previous"
+menuCloseWindow "&Close"
+menuListWindows "&List..."
+menuRefreshDisplay "&Refresh display"
+menuHelp "&Help"
+menuContents "&Contents"
+menuIndex "&Index"
+menuTopicSearch "&Topic search"
+menuPreviousTopic "&Previous topic"
+menuUsingHelp "&Using help"
+menuHelpFiles "&Files..."
+menuAbout "&About..."
+menuHelp "Help"
+menuSave "Save"
+menuOpen "Open"
+menuCompileAndRun "Compile & Run"
+menuLocalMenu "Local menu"

+ 47 - 8
src/FoStrings.Mod

@@ -1,20 +1,36 @@
 MODULE FoStrings;
 MODULE FoStrings;
-IMPORT Strings, Texts, Int, Out;
+IMPORT Strings, Texts, Int, Dir, Out;
+
+CONST
+  maxErrors = 500;
+  maxStrings = 2000;
 
 
 TYPE String = ARRAY 128 OF CHAR;
 TYPE String = ARRAY 128 OF CHAR;
+  Pair = RECORD
+    key: ARRAY 64 OF CHAR;
+    value: ARRAY 128 OF CHAR
+  END;
 
 
 VAR lang: ARRAY 6 OF CHAR;
 VAR lang: ARRAY 6 OF CHAR;
-  errorStr: ARRAY 500 OF String;
+  errorStr: ARRAY maxErrors OF String;
+  strings: ARRAY maxStrings OF Pair;
+  nofstrings: INTEGER; (* Actual length of strings *)
+
+PROCEDURE Get*(key: ARRAY OF CHAR; VAR value: ARRAY OF CHAR);
+VAR i: INTEGER;
+BEGIN i := 0;
+  WHILE (i # nofstrings) & (strings[i].key # key) DO INC(i) END;
+  IF i # nofstrings THEN Strings.Copy(strings[i].value, value)
+  ELSE Strings.Copy(key, value); Strings.Insert('#', 0, value)
+  END
+END Get;
 
 
 PROCEDURE GetErrorStr*(err: INTEGER; VAR s: ARRAY OF CHAR);
 PROCEDURE GetErrorStr*(err: INTEGER; VAR s: ARRAY OF CHAR);
 BEGIN
 BEGIN
   IF (0 <= err) & (err < LEN(errorStr)) THEN Strings.Copy(errorStr[err], s)
   IF (0 <= err) & (err < LEN(errorStr)) THEN Strings.Copy(errorStr[err], s)
   ELSE s := 'Text of error #'; Int.Append(err, s); Strings.Append('.', s)
   ELSE s := 'Text of error #'; Int.Append(err, s); Strings.Append('.', s)
   END
   END
-  (*IF err = 41 THEN s := 'Пропущена точка с запятой.'
-  ELSIF err = 257 THEN s := 'Файл содержит неверное имя модуля.'
-  ELSE s := 'Текст '; Int.Append(err, s); Strings.Append('-й ошибки.', s)
-  END*)
+  (*'Пропущена точка с запятой.' 'Файл содержит неверное имя модуля.'*)
 END GetErrorStr;
 END GetErrorStr;
 
 
 PROCEDURE MakeErrorStr*(err: INTEGER; VAR s: ARRAY OF CHAR);
 PROCEDURE MakeErrorStr*(err: INTEGER; VAR s: ARRAY OF CHAR);
@@ -36,16 +52,21 @@ BEGIN
   END
   END
 END Clear;
 END Clear;
 
 
+PROCEDURE GetLangFname(lang: ARRAY OF CHAR; VAR fname: ARRAY OF CHAR);
+BEGIN fname := 'Data/Texts/'; Strings.Append(lang, fname);
+  Strings.Append('.dat', fname)
+END GetLangFname;
+
 PROCEDURE LoadStrings;
 PROCEDURE LoadStrings;
 VAR T: Texts.Text;
 VAR T: Texts.Text;
   i: INTEGER;
   i: INTEGER;
   ok: BOOLEAN;
   ok: BOOLEAN;
   S: Texts.Scanner;
   S: Texts.Scanner;
   fname: ARRAY 256 OF CHAR;
   fname: ARRAY 256 OF CHAR;
+  key: ARRAY 64 OF CHAR;
 BEGIN
 BEGIN
   Clear;
   Clear;
-  fname := 'Data/Texts/'; Strings.Append(lang, fname);
-  Strings.Append('.dat', fname);
+  GetLangFname(lang, fname);
   NEW(T); Texts.Open(T, fname);
   NEW(T); Texts.Open(T, fname);
   Texts.OpenScanner(S, T, 0);
   Texts.OpenScanner(S, T, 0);
   Texts.Scan(S); ok := TRUE;
   Texts.Scan(S); ok := TRUE;
@@ -55,6 +76,18 @@ BEGIN
          (S.len < LEN(errorStr[0]) - 1)
          (S.len < LEN(errorStr[0]) - 1)
       THEN Strings.Copy(S.s, errorStr[i]); ok := TRUE
       THEN Strings.Copy(S.s, errorStr[i]); ok := TRUE
       END
       END
+    ELSIF (S.class = Texts.Name) & (S.len < LEN(key) - 1) THEN
+      Strings.Copy(S.s, key); Texts.Scan(S);
+      IF (S.class = Texts.String) & (0 <= i) & (i < LEN(strings)) &
+         (S.len < LEN(strings[0].value) - 1)
+      THEN
+        IF nofstrings < LEN(strings) THEN ok := TRUE;
+          Strings.Copy(key, strings[nofstrings].key);
+          Strings.Copy(S.s, strings[nofstrings].value);
+          INC(nofstrings)
+        ELSE Out.String('Too many strings in a language file.'); Out.Ln
+        END
+      END
     END;
     END;
     Texts.Scan(S)
     Texts.Scan(S)
   END;
   END;
@@ -64,8 +97,14 @@ BEGIN
   END
   END
 END LoadStrings;
 END LoadStrings;
 
 
+PROCEDURE LangExists*(language: ARRAY OF CHAR): BOOLEAN;
+VAR fname: ARRAY 256 OF CHAR;
+BEGIN GetLangFname(language, fname)
+RETURN Dir.FileExists(fname) END LangExists;
+
 PROCEDURE SetLang*(language: ARRAY OF CHAR);
 PROCEDURE SetLang*(language: ARRAY OF CHAR);
 BEGIN lang := language; LoadStrings
 BEGIN lang := language; LoadStrings
 END SetLang;
 END SetLang;
 
 
+BEGIN nofstrings := 0; Clear
 END FoStrings.
 END FoStrings.

+ 92 - 9
src/FreeOberon.Mod

@@ -976,147 +976,226 @@ END CascadeWindows;
 
 
 PROCEDURE InitIDE;
 PROCEDURE InitIDE;
 VAR w: OV.Window;
 VAR w: OV.Window;
-    m, m2: OV.Menu;
+  m, m2: OV.Menu;
+  s, q: ARRAY 256 OF CHAR;
 BEGIN
 BEGIN
   app := OV.NewApp();
   app := OV.NewApp();
   FileNew(app.menu);
   FileNew(app.menu);
 
 
-  m := OV.NewMenu('&File', '', 0, NIL);
+  FoStrings.Get('menuFile', s);
+  m := OV.NewMenu(s, '', 0, NIL);
   OV.Add(m, OV.NewMenu('&New', 'Shift+F3', OV.hShiftF3, FileNew));
   OV.Add(m, OV.NewMenu('&New', 'Shift+F3', OV.hShiftF3, FileNew));
-  OV.Add(m, OV.NewMenu('&Open', 'F3', OV.hF3, FileOpen));
-  OV.Add(m, OV.NewMenu('&Reload', '', 0, FileReload));
-  OV.Add(m, OV.NewMenu('&Save', 'F2', OV.hF2, FileSave));
+  FoStrings.Get('menuOpen', s);
+  OV.Add(m, OV.NewMenu(s, 'F3', OV.hF3, FileOpen));
+  FoStrings.Get('menuReload', s);
+  OV.Add(m, OV.NewMenu(s, '', 0, FileReload));
+  FoStrings.Get('menuSave', s);
+  OV.Add(m, OV.NewMenu(s, 'F2', OV.hF2, FileSave));
+  FoStrings.Get('menuSaveAs', s);
   OV.Add(m, OV.NewMenu('Save &as...', 'Shift+F2', OV.hShiftF2, FileSaveAs));
   OV.Add(m, OV.NewMenu('Save &as...', 'Shift+F2', OV.hShiftF2, FileSaveAs));
-  (*OV.Add(m, OV.NewMenu('Save a&ll', '', 0, NIL));*)
+  (*FoStrings.Get('menuSaveAll', s);*)
+  (*OV.Add(m, OV.NewMenu(s, '', 0, NIL));*)
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
-  OV.Add(m, OV.NewMenu('E&xit', 'Alt+X', OV.hAltX, OV.QuitApp));
+  FoStrings.Get('menuExit', s);
+  OV.Add(m, OV.NewMenu(s, 'Alt+X', OV.hAltX, OV.QuitApp));
   OV.AddMenu(app, m);
   OV.AddMenu(app, m);
+  FoStrings.Get('menuEdit', s);
   m := OV.NewMenu('&Edit', '', 0, NIL);
   m := OV.NewMenu('&Edit', '', 0, NIL);
+  FoStrings.Get('menuUndo', s);
   m2 := OV.NewMenu('&Undo', 'DelText', OV.hAltBackspace, NIL); m2.status := OV.disabled;
   m2 := OV.NewMenu('&Undo', 'DelText', OV.hAltBackspace, NIL); m2.status := OV.disabled;
   OV.Add(m, m2);
   OV.Add(m, m2);
+  FoStrings.Get('menuRedo', s);
   m2 := OV.NewMenu('&Redo', '', 0, NIL); m2.status := OV.disabled;
   m2 := OV.NewMenu('&Redo', '', 0, NIL); m2.status := OV.disabled;
   OV.Add(m, m2);
   OV.Add(m, m2);
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
+  FoStrings.Get('menuCut', s);
   OV.Add(m, OV.NewMenu('Cu&t', 'Ctrl+X', OV.hCtrlX, Editor.EditCut));
   OV.Add(m, OV.NewMenu('Cu&t', 'Ctrl+X', OV.hCtrlX, Editor.EditCut));
+  FoStrings.Get('menuCopy', s);
   OV.Add(m, OV.NewMenu('&Copy', 'Ctrl+C', OV.hCtrlC, Editor.EditCopy));
   OV.Add(m, OV.NewMenu('&Copy', 'Ctrl+C', OV.hCtrlC, Editor.EditCopy));
+  FoStrings.Get('menuPaste', s);
   OV.Add(m, OV.NewMenu('&Paste', 'Ctrl+V', OV.hCtrlV, Editor.EditPaste));
   OV.Add(m, OV.NewMenu('&Paste', 'Ctrl+V', OV.hCtrlV, Editor.EditPaste));
+  FoStrings.Get('menuClear', s);
   OV.Add(m, OV.NewMenu('C&lear', 'Ctrl+Del', OV.hCtrlDel, Editor.EditClear));
   OV.Add(m, OV.NewMenu('C&lear', 'Ctrl+Del', OV.hCtrlDel, Editor.EditClear));
+  FoStrings.Get('menuSelectAll', s);
   OV.Add(m, OV.NewMenu('Select &All', 'Ctrl+A', OV.hCtrlA, Editor.EditSelectAll));
   OV.Add(m, OV.NewMenu('Select &All', 'Ctrl+A', OV.hCtrlA, Editor.EditSelectAll));
+  FoStrings.Get('menuUnselect', s);
   OV.Add(m, OV.NewMenu('U&nselect', '', 0, Editor.EditUnselect));
   OV.Add(m, OV.NewMenu('U&nselect', '', 0, Editor.EditUnselect));
   OV.AddMenu(app, m);
   OV.AddMenu(app, m);
+  FoStrings.Get('menuSearch', s);
   m := OV.NewMenu('&Search', '', 0, NIL);
   m := OV.NewMenu('&Search', '', 0, NIL);
+  FoStrings.Get('menuFind', s);
   OV.Add(m, OV.NewMenu('&Find...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Find...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuReplace', s);
   OV.Add(m, OV.NewMenu('&Replace...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Replace...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuSearchAgain', s);
   OV.Add(m, OV.NewMenu('&Search again', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Search again', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
+  FoStrings.Get('menuGoToLineNumber', s);
   OV.Add(m, OV.NewMenu('&Go to line number...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Go to line number...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuFindProcedure', s);
   OV.Add(m, OV.NewMenu('&Find procedure...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Find procedure...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
   OV.AddMenu(app, m);
   OV.AddMenu(app, m);
+  FoStrings.Get('menuRun', s);
   m := OV.NewMenu('&Run', '', 0, NIL);
   m := OV.NewMenu('&Run', '', 0, NIL);
   OV.Add(m, OV.NewMenu('&Run', 'Ctrl+F9', OV.hCtrlF9, OnBuild));
   OV.Add(m, OV.NewMenu('&Run', 'Ctrl+F9', OV.hCtrlF9, OnBuild));
+  FoStrings.Get('menuRunDirectory', s);
   OV.Add(m, OV.NewMenu('Run &Directory...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('Run &Directory...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuParameters', s);
   OV.Add(m, OV.NewMenu('P&arameters...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('P&arameters...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
   OV.AddMenu(app, m);
   OV.AddMenu(app, m);
+  FoStrings.Get('menuCompile', s);
   m := OV.NewMenu('&Compile', '', 0, NIL);
   m := OV.NewMenu('&Compile', '', 0, NIL);
   OV.Add(m, OV.NewMenu('&Compile', 'Alt+F9', OV.hAltF9, OnBuild));
   OV.Add(m, OV.NewMenu('&Compile', 'Alt+F9', OV.hAltF9, OnBuild));
+  FoStrings.Get('menuMake', s);
   OV.Add(m, OV.NewMenu('&Make', 'Shift+F9', OV.hShiftF9, OnBuild));
   OV.Add(m, OV.NewMenu('&Make', 'Shift+F9', OV.hShiftF9, OnBuild));
+  FoStrings.Get('menuMakeAndRun', s);
   OV.Add(m, OV.NewMenu('Make && &Run', 'F9', OV.hF9, OnBuild));
   OV.Add(m, OV.NewMenu('Make && &Run', 'F9', OV.hF9, OnBuild));
+  FoStrings.Get('menuBuild', s);
   OV.Add(m, OV.NewMenu('&Build', '', 0, OnBuild));
   OV.Add(m, OV.NewMenu('&Build', '', 0, OnBuild));
   OV.AddMenu(app, m);
   OV.AddMenu(app, m);
+  FoStrings.Get('menuDebug', s);
   m := OV.NewMenu('&Debug', '', 0, NIL);
   m := OV.NewMenu('&Debug', '', 0, NIL);
+  FoStrings.Get('menuOutput', s);
   OV.Add(m, OV.NewMenu('&Output', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Output', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
   OV.AddMenu(app, m);
   OV.AddMenu(app, m);
+  FoStrings.Get('menuTools', s);
   m := OV.NewMenu('&Tools', '', 0, NIL);
   m := OV.NewMenu('&Tools', '', 0, NIL);
+  FoStrings.Get('menuMessages', s);
   OV.Add(m, OV.NewMenu('&Messages', 'F11', OV.hF11, NIL));
   OV.Add(m, OV.NewMenu('&Messages', 'F11', OV.hF11, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
+  FoStrings.Get('menuCalculator', s);
   OV.Add(m, OV.NewMenu('&Calculator', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Calculator', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuAsciiTable', s);
   OV.Add(m, OV.NewMenu('Ascii &table', '', 0, NIL));
   OV.Add(m, OV.NewMenu('Ascii &table', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
   OV.AddMenu(app, m);
   OV.AddMenu(app, m);
+  FoStrings.Get('menuOptions', s);
   m := OV.NewMenu('&Options', '', 0, NIL);
   m := OV.NewMenu('&Options', '', 0, NIL);
-  OV.Add(m, OV.NewMenu('Mode&...', 'Normal', 0, NIL));
+  FoStrings.Get('menuMode', s);
+  FoStrings.Get('menuNormalMode', q);
+  OV.Add(m, OV.NewMenu('Mode&...', q, 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuCompiler', s);
   OV.Add(m, OV.NewMenu('&Compiler...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Compiler...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuMemorySizes', s);
   OV.Add(m, OV.NewMenu('&Memory sizes...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Memory sizes...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuLinker', s);
   OV.Add(m, OV.NewMenu('&Linker...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Linker...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuDirectories', s);
   OV.Add(m, OV.NewMenu('&Directories...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Directories...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuTools', s);
   OV.Add(m, OV.NewMenu('&Tools...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Tools...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
+  FoStrings.Get('menuEnvironment', s);
   m2 := OV.NewMenu('&Environment', '', 0, NIL);
   m2 := OV.NewMenu('&Environment', '', 0, NIL);
+  FoStrings.Get('menuPreferences', s);
   OV.Add(m2, OV.NewMenu('&Preferences...', '', 0, NIL));
   OV.Add(m2, OV.NewMenu('&Preferences...', '', 0, NIL));
   (*!TODO*) m2.children.prev.status := OV.disabled;
   (*!TODO*) m2.children.prev.status := OV.disabled;
+  FoStrings.Get('menuEditor', s);
   OV.Add(m2, OV.NewMenu('&Editor...', '', 0, NIL));
   OV.Add(m2, OV.NewMenu('&Editor...', '', 0, NIL));
   (*!TODO*) m2.children.prev.status := OV.disabled;
   (*!TODO*) m2.children.prev.status := OV.disabled;
+  FoStrings.Get('menuCodeComplete', s);
   OV.Add(m2, OV.NewMenu('Code&Complete...', '', 0, NIL));
   OV.Add(m2, OV.NewMenu('Code&Complete...', '', 0, NIL));
   (*!TODO*) m2.children.prev.status := OV.disabled;
   (*!TODO*) m2.children.prev.status := OV.disabled;
+  FoStrings.Get('menuCodeTemplates', s);
   OV.Add(m2, OV.NewMenu('Code&Templates...', '', 0, NIL));
   OV.Add(m2, OV.NewMenu('Code&Templates...', '', 0, NIL));
   (*!TODO*) m2.children.prev.status := OV.disabled;
   (*!TODO*) m2.children.prev.status := OV.disabled;
+  FoStrings.Get('menuDesktop', s);
   OV.Add(m2, OV.NewMenu('&Desktop...', '', 0, NIL));
   OV.Add(m2, OV.NewMenu('&Desktop...', '', 0, NIL));
   (*!TODO*) m2.children.prev.status := OV.disabled;
   (*!TODO*) m2.children.prev.status := OV.disabled;
+  FoStrings.Get('menuKeyboardAndMouse', s);
   OV.Add(m2, OV.NewMenu('Keyboard && &mouse...', '', 0, NIL));
   OV.Add(m2, OV.NewMenu('Keyboard && &mouse...', '', 0, NIL));
   (*!TODO*) m2.children.prev.status := OV.disabled;
   (*!TODO*) m2.children.prev.status := OV.disabled;
+  FoStrings.Get('menuLearnKeys', s);
   OV.Add(m2, OV.NewMenu('Learn &Keys', '', 0, NIL));
   OV.Add(m2, OV.NewMenu('Learn &Keys', '', 0, NIL));
   (*!TODO*) m2.children.prev.status := OV.disabled;
   (*!TODO*) m2.children.prev.status := OV.disabled;
   OV.Add(m, m2);
   OV.Add(m, m2);
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
+  FoStrings.Get('menuOpenOptions', s);
   OV.Add(m, OV.NewMenu('&Open...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Open...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuSaveOptions', s);
   OV.Add(m, OV.NewMenu('&Save', 'fo.ini', 0, NIL));
   OV.Add(m, OV.NewMenu('&Save', 'fo.ini', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuSaveOptionsAs', s);
   OV.Add(m, OV.NewMenu('Save &as...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('Save &as...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
   OV.AddMenu(app, m);
   OV.AddMenu(app, m);
+  FoStrings.Get('menuWindow', s);
   m := OV.NewMenu('&Window', '', 0, NIL);
   m := OV.NewMenu('&Window', '', 0, NIL);
+  FoStrings.Get('menuTile', s);
   OV.Add(m, OV.NewMenu('&Tile', '', 0, TileWindows));
   OV.Add(m, OV.NewMenu('&Tile', '', 0, TileWindows));
+  FoStrings.Get('menuCascade', s);
   OV.Add(m, OV.NewMenu('C&ascade', '', 0, CascadeWindows));
   OV.Add(m, OV.NewMenu('C&ascade', '', 0, CascadeWindows));
+  FoStrings.Get('menuCloseAll', s);
   OV.Add(m, OV.NewMenu('Cl&ose all', '', 0, OV.CloseAllWindows));
   OV.Add(m, OV.NewMenu('Cl&ose all', '', 0, OV.CloseAllWindows));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
+  FoStrings.Get('menuSizeMove', s);
   OV.Add(m, OV.NewMenu('&Size/Move', 'Ctrl+F5', OV.hCtrlF5, NIL));
   OV.Add(m, OV.NewMenu('&Size/Move', 'Ctrl+F5', OV.hCtrlF5, NIL));
+  FoStrings.Get('menuZoom', s);
   OV.Add(m, OV.NewMenu('&Zoom', 'F5', OV.hF5, OV.ZoomCurWindow));
   OV.Add(m, OV.NewMenu('&Zoom', 'F5', OV.hF5, OV.ZoomCurWindow));
+  FoStrings.Get('menuNextWindow', s);
   OV.Add(m, OV.NewMenu('&Next', 'F6', OV.hF6, OV.NextWindow));
   OV.Add(m, OV.NewMenu('&Next', 'F6', OV.hF6, OV.NextWindow));
+  FoStrings.Get('menuPreviousWindow', s);
   OV.Add(m, OV.NewMenu('&Previous', 'Shift+F6', OV.hShiftF6, OV.PrevWindow));
   OV.Add(m, OV.NewMenu('&Previous', 'Shift+F6', OV.hShiftF6, OV.PrevWindow));
+  FoStrings.Get('menuCloseWindow', s);
   OV.Add(m, OV.NewMenu('&Close', 'Alt+F3', OV.hAltF3, OV.CloseCurWindow));
   OV.Add(m, OV.NewMenu('&Close', 'Alt+F3', OV.hAltF3, OV.CloseCurWindow));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
+  FoStrings.Get('menuListWindows', s);
   OV.Add(m, OV.NewMenu('&List...', 'Alt+0', OV.hAlt0, NIL));
   OV.Add(m, OV.NewMenu('&List...', 'Alt+0', OV.hAlt0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuRefreshDisplay', s);
   OV.Add(m, OV.NewMenu('&Refresh display', '', 0, OV.RefreshDisplay));
   OV.Add(m, OV.NewMenu('&Refresh display', '', 0, OV.RefreshDisplay));
   OV.AddMenu(app, m);
   OV.AddMenu(app, m);
+  FoStrings.Get('menuHelp', s);
   m := OV.NewMenu('&Help', '', 0, NIL);
   m := OV.NewMenu('&Help', '', 0, NIL);
+  FoStrings.Get('menuContents', s);
   OV.Add(m, OV.NewMenu('&Contents', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Contents', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuIndex', s);
   OV.Add(m, OV.NewMenu('&Index', 'Shift+F1', OV.hShiftF1, NIL));
   OV.Add(m, OV.NewMenu('&Index', 'Shift+F1', OV.hShiftF1, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuTopicSearch', s);
   OV.Add(m, OV.NewMenu('&Topic search', 'Ctrl+F1', OV.hCtrlF1, NIL));
   OV.Add(m, OV.NewMenu('&Topic search', 'Ctrl+F1', OV.hCtrlF1, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuPreviousTopic', s);
   OV.Add(m, OV.NewMenu('&Previous topic', 'Alt+F1', OV.hAltF1, NIL));
   OV.Add(m, OV.NewMenu('&Previous topic', 'Alt+F1', OV.hAltF1, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuUsingHelp', s);
   OV.Add(m, OV.NewMenu('&Using help', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Using help', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
+  FoStrings.Get('menuHelpFiles', s);
   OV.Add(m, OV.NewMenu('&Files...', '', 0, NIL));
   OV.Add(m, OV.NewMenu('&Files...', '', 0, NIL));
   (*!TODO*) m.children.prev.status := OV.disabled;
   (*!TODO*) m.children.prev.status := OV.disabled;
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
   OV.Add(m, OV.NewMenu('-', '', 0, NIL));
+  FoStrings.Get('menuAbout', s);
   OV.Add(m, OV.NewMenu('&About...', '', OV.hF1, HelpAbout));
   OV.Add(m, OV.NewMenu('&About...', '', OV.hF1, HelpAbout));
   OV.AddMenu(app, m);
   OV.AddMenu(app, m);
 
 
+  FoStrings.Get('menuHelp', s);
   OV.AddStatusbar(app, OV.NewQuickBtn('Help', 'F1', 0, HelpAbout));
   OV.AddStatusbar(app, OV.NewQuickBtn('Help', 'F1', 0, HelpAbout));
+  FoStrings.Get('menuSave', s);
   OV.AddStatusbar(app, OV.NewQuickBtn('Save', 'F2', 0, FileSave));
   OV.AddStatusbar(app, OV.NewQuickBtn('Save', 'F2', 0, FileSave));
+  FoStrings.Get('menuOpen', s);
   OV.AddStatusbar(app, OV.NewQuickBtn('Open', 'F3', 0, FileOpen));
   OV.AddStatusbar(app, OV.NewQuickBtn('Open', 'F3', 0, FileOpen));
+  FoStrings.Get('menuCompileAndRun', s);
   OV.AddStatusbar(app, OV.NewQuickBtn('Compile & Run', 'F9', 0, OnBuild));
   OV.AddStatusbar(app, OV.NewQuickBtn('Compile & Run', 'F9', 0, OnBuild));
+  FoStrings.Get('menuLocalMenu', s);
   OV.AddStatusbar(app, OV.NewQuickBtn('Local menu', 'Alt+F10', 0, NIL))
   OV.AddStatusbar(app, OV.NewQuickBtn('Local menu', 'Alt+F10', 0, NIL))
 END InitIDE;
 END InitIDE;
 
 
@@ -1174,7 +1253,11 @@ BEGIN fs := TRUE; sw := FALSE; i := 1; nofnames := 0; w := defW; h := defH;
       END
       END
     ELSIF s = '--lang' THEN
     ELSIF s = '--lang' THEN
       IF i + 1 # Args.argc THEN
       IF i + 1 # Args.argc THEN
-        INC(i); Args.Get(i, q); Utf8.Decode(q, lang)
+        INC(i); Args.Get(i, q); Utf8.Decode(q, lang);
+        IF ~FoStrings.LangExists(lang) THEN Out.String('Language "');
+          Out.String(lang); Out.String('" does not exist.'); Out.Ln;
+          lang := defLang
+        END
       END
       END
     ELSIF nofnames < LEN(fnames) THEN
     ELSIF nofnames < LEN(fnames) THEN
       ParseFileNameArg(s);
       ParseFileNameArg(s);