i18n
This commit is contained in:
1 parent
40ae451bef
commit
74c57f9433
7 files changed
+88
-48
No files matched your search
+9
-9
@@ -1,4 +1,8 @@
|
||||
from kivy.config import Config # isort:skip
|
||||
ICON = "img/icon.png" # isort:skip # set icon
|
||||
Config.set("kivy", "window_icon", ICON) # isort:skip # set icon
|
||||
Config.set("input", "mouse", "mouse,multitouch_on_demand") # isort:skip # no red dots on right click
|
||||
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
@@ -24,22 +28,18 @@ from katrain.core.common import (
|
||||
OUTPUT_EXTRA_DEBUG,
|
||||
OUTPUT_INFO,
|
||||
OUTPUT_KATAGO_STDERR,
|
||||
Lang,
|
||||
find_package_resource,
|
||||
find_package_resource,i18n
|
||||
)
|
||||
from katrain.core.engine import KataGoEngine
|
||||
from katrain.core.game import Game, IllegalMoveException, KaTrainSGF
|
||||
from katrain.core.sgf_parser import Move, ParseError
|
||||
from katrain.gui.badukpan import AnalysisControls, BadukPanControls, BadukPanWidget
|
||||
from katrain.gui.controlspanel import ControlsPanel, RightButtonControls
|
||||
from katrain.gui.controlspanel import ControlsPanel
|
||||
from katrain.gui.graph import ScoreGraph
|
||||
from katrain.gui.kivyutils import *
|
||||
from katrain.gui.popups import ConfigPopup, LoadSGFPopup, NewGamePopup
|
||||
from katrain.gui.style import ENGINE_BUSY_COL, ENGINE_DOWN_COL, ENGINE_READY_COL
|
||||
|
||||
ICON = "img/icon.png"
|
||||
Config.set("kivy", "window_icon", ICON) # isort:skip # set icon
|
||||
Config.set("input", "mouse", "mouse,multitouch_on_demand") # isort:skip # no red dots on right click
|
||||
|
||||
|
||||
__version__ = "1.1.0"
|
||||
@@ -229,7 +229,7 @@ class KaTrainGui(Screen):
|
||||
try:
|
||||
move_tree = KaTrainSGF.parse_file(files[0])
|
||||
except ParseError as e:
|
||||
self.log(f"Failed to load SGF. Parse Error: {e}", OUTPUT_ERROR)
|
||||
self.log(i18n._("Failed to load SGF").format(error=e), OUTPUT_ERROR)
|
||||
return
|
||||
self._do_new_game(move_tree=move_tree, analyze_fast=popup_contents.fast.active)
|
||||
if not popup_contents.rewind.active:
|
||||
@@ -276,7 +276,7 @@ class KaTrainGui(Screen):
|
||||
try:
|
||||
move_tree = KaTrainSGF.parse(clipboard)
|
||||
except Exception as e:
|
||||
self.controls.set_status(f"Failed to imported game from clipboard: {e}\nClipboard contents: {clipboard[:50]}...")
|
||||
self.controls.set_status(i18n._("Failed to import from clipboard").format(error=e,contents=clipboard[:50]))
|
||||
return
|
||||
move_tree.nodes_in_tree[-1].analyze(self.engine, analyze_fast=False) # speed up result for looking at end of game
|
||||
self._do_new_game(move_tree=move_tree, analyze_fast=True)
|
||||
@@ -332,7 +332,7 @@ class KaTrainGui(Screen):
|
||||
self("output-sgf")
|
||||
elif keycode[1] == "c" and "ctrl" in modifiers:
|
||||
Clipboard.copy(self.game.root.sgf())
|
||||
self.controls.set_status("Copied SGF to clipboard.")
|
||||
self.controls.set_status(i18n._("Copied SGF to clipboard."))
|
||||
elif keycode[1] == "v" and "ctrl" in modifiers:
|
||||
self.load_sgf_from_clipboard()
|
||||
return True
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import os
|
||||
import sys
|
||||
from typing import Any, List, Tuple
|
||||
from kivy.lang import Observable
|
||||
import gettext
|
||||
from kivy.uix.label import Label
|
||||
from kivy.uix.textinput import TextInput
|
||||
from kivy.core.text import Label as CoreLabel
|
||||
|
||||
try:
|
||||
import importlib.resources as pkg_resources
|
||||
@@ -44,7 +44,7 @@ def find_package_resource(path):
|
||||
with pkg_resources.path(".".join(parts[:-1]), parts[-1]) as path_obj:
|
||||
return str(path_obj) # this will clean up if egg etc, but these don't work anyway
|
||||
except (ModuleNotFoundError, FileNotFoundError) as e:
|
||||
print(f"File {path} not found, installation possibly broken")
|
||||
print(f"File {path} not found, installation possibly broken",file=sys.stderr)
|
||||
return f"FILENOTFOUND::{path}"
|
||||
else:
|
||||
return path # absolute path
|
||||
@@ -101,10 +101,5 @@ i18n = Lang(LANGUAGE)
|
||||
class I18NLabel(Label):
|
||||
pass
|
||||
|
||||
|
||||
class I18NCoreLabel(CoreLabel):
|
||||
pass
|
||||
|
||||
|
||||
class I18NTextInput(TextInput):
|
||||
pass
|
||||
+6
-11
@@ -6,7 +6,7 @@ import threading
|
||||
import time
|
||||
from typing import Callable, Optional
|
||||
|
||||
from katrain.core.common import OUTPUT_DEBUG, OUTPUT_ERROR, OUTPUT_EXTRA_DEBUG, OUTPUT_KATAGO_STDERR, find_package_resource
|
||||
from katrain.core.common import OUTPUT_DEBUG, OUTPUT_ERROR, OUTPUT_EXTRA_DEBUG, OUTPUT_KATAGO_STDERR, find_package_resource, i18n
|
||||
from katrain.core.game_node import GameNode
|
||||
|
||||
|
||||
@@ -56,16 +56,11 @@ class KataGoEngine:
|
||||
self.katrain.log(f"Starting KataGo with {self.command}", OUTPUT_DEBUG)
|
||||
self.katago_process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except (FileNotFoundError, PermissionError, OSError) as e:
|
||||
if self.config["katago"].strip():
|
||||
self.katrain.log(
|
||||
f"Starting kata with command '{self.command}' failed with error {e}. If on MacOS, see the manual on how to use brew to install katago first, and add it to your path or 'engine/katago' setting.",
|
||||
OUTPUT_ERROR,
|
||||
if not self.config["katago"].strip():
|
||||
self.katrain.log( i18n._("Starting default Kata failed").format(command=self.comment,error=e), OUTPUT_ERROR,
|
||||
)
|
||||
else:
|
||||
self.katrain.log(
|
||||
f"Starting kata with command '{self.command}' failed with error {e}. Please make sure the 'katago' value under 'engine' in settings points to the correct KataGo executable.",
|
||||
OUTPUT_ERROR,
|
||||
)
|
||||
self.katrain.log( i18n._("Starting Kata failed").format(command=self.comment,error=e) , OUTPUT_ERROR, )
|
||||
self.analysis_thread = threading.Thread(target=self._analysis_read_thread, daemon=True).start()
|
||||
self.stderr_thread = threading.Thread(target=self._read_stderr_thread, daemon=True).start()
|
||||
|
||||
@@ -108,7 +103,7 @@ class KataGoEngine:
|
||||
try:
|
||||
line = self.katago_process.stdout.readline()
|
||||
except OSError as e:
|
||||
raise EngineDiedException(f"Engine died unexpectedly without sending output, possibly due to out of memory: {e}")
|
||||
raise EngineDiedException(i18n("Engine died unexpectedly").format(error=e))
|
||||
if b"Uncaught exception" in line:
|
||||
self.katrain.log(f"KataGo Engine Failed: {line.decode()}", OUTPUT_ERROR)
|
||||
return
|
||||
@@ -152,7 +147,7 @@ class KataGoEngine:
|
||||
self.katago_process.stdin.write((json.dumps(query) + "\n").encode())
|
||||
self.katago_process.stdin.flush()
|
||||
except OSError as e:
|
||||
self.katrain.log(f"Engine died unexpectedly, possibly due to out of memory: {e}", OUTPUT_ERROR)
|
||||
self.katrain.log(i18n._("Engine died unexpectedly").format(error=e), OUTPUT_ERROR)
|
||||
return # do not raise, since there's nothing to catch it
|
||||
|
||||
def request_analysis(
|
||||
|
||||
+12
-12
@@ -2,7 +2,7 @@ import copy
|
||||
import random
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
from katrain.core.common import evaluation_class, var_to_grid
|
||||
from katrain.core.common import evaluation_class, var_to_grid, i18n
|
||||
from katrain.core.sgf_parser import Move, SGFNode
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class GameNode(SGFNode):
|
||||
properties["C"] = ["\n".join(properties.get("C", "")) + comment]
|
||||
if self.is_root:
|
||||
properties["C"] = [
|
||||
"Moves marked 'X' indicate the top move according to KataGo, those with a square are moves that lose less than 0.5 points.\n"
|
||||
i18n._("SGF start message") + "\n"
|
||||
+ "\n".join(properties.get("C", ""))
|
||||
+ "\nSGF with review generated by KaTrain."
|
||||
]
|
||||
@@ -137,29 +137,29 @@ class GameNode(SGFNode):
|
||||
if previous_top_move["move"] != single_move.gtp():
|
||||
points_lost = self.points_lost
|
||||
if sgf and points_lost > 0.5:
|
||||
text += f"Estimated point loss: {points_lost:.1f}\n"
|
||||
text += f"Predicted top move was {previous_top_move['move']} ({self.format_score(previous_top_move['scoreLead'])}).\n"
|
||||
text += i18n._("Info:point loss").format(points=points_lost) + "\n"
|
||||
text += i18n._("Info:top move").format(top_move=previous_top_move['move'],score=self.format_score(previous_top_move['scoreLead'])) +".\n"
|
||||
else:
|
||||
text += f"Move was predicted best move.\n"
|
||||
text += i18n._("Info:best move")+"\n"
|
||||
if previous_top_move.get("pv") and (sgf or hints):
|
||||
text += f"PV: {self.make_pv(single_move.player,previous_top_move['pv'],interactive)}\n"
|
||||
text += i18n._("Info:PV") + ": " + self.make_pv(single_move.player,previous_top_move['pv'],interactive) + "\n"
|
||||
|
||||
if sgf or hints or teach:
|
||||
policy_ranking = self.parent.policy_ranking
|
||||
currmove_policy_with_ix = [(ix + 1, p) for (p, m), ix in zip(policy_ranking, range(len(policy_ranking))) if m == single_move]
|
||||
if currmove_policy_with_ix:
|
||||
text += f"Move was #{currmove_policy_with_ix[0][0]} according to policy ({currmove_policy_with_ix[0][1]:.2%}).\n"
|
||||
text += i18n._("Info:policy rank").format(rank=currmove_policy_with_ix[0][0],probability=currmove_policy_with_ix[0][1]) + "\n"
|
||||
if not currmove_policy_with_ix or currmove_policy_with_ix[0] != 1 and (sgf or hints):
|
||||
text += f"Top policy move was {policy_ranking[0][1].gtp()} ({policy_ranking[0][0]:.1%}).\n"
|
||||
text += i18n._("Info:policy best").format(move=policy_ranking[0][1].gtp(),probability=policy_ranking[0][0]) +".\n"
|
||||
if self.auto_undo and sgf:
|
||||
text += "Move was automatically undone in teaching mode.\n"
|
||||
text += i18n._("Info:teaching undo") + "\n"
|
||||
top_pv = self.analysis_ready and self.candidate_moves[0].get("pv")
|
||||
if top_pv:
|
||||
text += f"Predicted follow-up: {self.next_player}{' '.join(top_pv)}\n"
|
||||
text += i18n._("Info:undo predicted PV").format(pv=f"{self.next_player}{' '.join(top_pv)}") + "\n"
|
||||
if self.ai_thoughts and (sgf or hints):
|
||||
text += f"\nAI thought process: {self.ai_thoughts}"
|
||||
text += "\n" + i18n._("Info:AI thoughts").format(thoughts=self.ai_thoughts)
|
||||
else:
|
||||
text = "No analysis available" if sgf else "Analyzing move..."
|
||||
text = i18n._("No analysis available") if sgf else i18n._("Analyzing move...")
|
||||
return text
|
||||
|
||||
@property
|
||||
|
||||
@@ -11,9 +11,6 @@ from katrain.gui.popups import ConfigTeacherPopup, ConfigTimerPopup
|
||||
from katrain.gui.ai_settings import ConfigAIPopupContents
|
||||
|
||||
|
||||
class RightButtonControls(MDBoxLayout):
|
||||
button_size = ListProperty([100, 33])
|
||||
|
||||
|
||||
class ControlsPanel(BoxLayout):
|
||||
katrain = ObjectProperty(None)
|
||||
|
||||
@@ -13,9 +13,7 @@ msgstr "Roboto"
|
||||
msgid "Hello World"
|
||||
msgstr "Hello World"
|
||||
|
||||
msgid "KataGo"
|
||||
msgstr "KataGo"
|
||||
|
||||
#.
|
||||
msgid "English"
|
||||
msgstr "English"
|
||||
|
||||
@@ -33,6 +31,7 @@ msgstr ""
|
||||
"[space]\n"
|
||||
"Pass"
|
||||
|
||||
#. tabs and labels on the right panel
|
||||
msgid "tab:score"
|
||||
msgstr "Score"
|
||||
|
||||
@@ -57,6 +56,7 @@ msgstr "Move Stats"
|
||||
msgid "closedlabel:info¬es"
|
||||
msgstr "Move Info & Notes"
|
||||
|
||||
#. on the board after pass
|
||||
msgid "board-pass"
|
||||
msgstr "pass"
|
||||
|
||||
@@ -64,3 +64,59 @@ msgid "board-game-end"
|
||||
msgstr ""
|
||||
"game\n"
|
||||
"end"
|
||||
|
||||
#. SGF and move comment messages
|
||||
msgid "SGF start message"
|
||||
msgstr "Moves marked 'X' indicate the top move according to KataGo, those with a square are moves that lose less than 0.5 points.
|
||||
|
||||
msgid "Info:point loss"
|
||||
msgstr "Estimated point loss: {points_lost:.1f}"
|
||||
|
||||
msgid "Info:top move"
|
||||
msgid "Predicted top move was {top_move} ({score})."
|
||||
|
||||
msgid "Info:best move"
|
||||
msgstr "Move was predicted best move.
|
||||
|
||||
msgid "Info:PV"
|
||||
msgstr "PV"
|
||||
|
||||
msgid "Info:policy rank"
|
||||
msgstr "Move was #{rank} according to policy ({probability:.2%})."
|
||||
|
||||
msgid "Info:policy best"
|
||||
msgstr "Top policy move was {move} ({policy_ranking[0][0]:.1%})."
|
||||
|
||||
msgid "Info:teaching undo"
|
||||
msgstr "Move was automatically undone in teaching mode."
|
||||
|
||||
msgid "Info:undo predicted PV"
|
||||
msgstr "Predicted follow-up: {pv}"
|
||||
|
||||
msgid "Info:AI thoughts"
|
||||
msgstr "AI thought process: {thoughts}"
|
||||
|
||||
msgid "No analysis available"
|
||||
msgstr "No analysis available"
|
||||
|
||||
msgid "Analyzing move..."
|
||||
msgstr "Analyzing move..."
|
||||
|
||||
#.misc errors and info messages
|
||||
msgid "Copied SGF to clipboard."
|
||||
msgstr "Copied SGF to clipboard."
|
||||
|
||||
msgid "Failed to import from clipboard"
|
||||
msgstr "Failed to import game from clipboard: {error}\nClipboard contents: {contents}..."
|
||||
|
||||
msgid "Failed to load SGF"
|
||||
msgstr "Failed to load SGF. Parse Error: {error}"
|
||||
|
||||
msgid "Starting default Kata failed"
|
||||
msgstr "Starting KataGo with command '{command}' failed with error {error}. If on MacOS, see the manual on how to use brew to install katago first, and add it to your path or 'engine/katago' setting."
|
||||
|
||||
msgid "Starting Kata failed"
|
||||
msgstr "Starting kata with command '{command}' failed with error {error}. Please make sure the 'katago' value under 'engine' in settings points to the correct KataGo executable."
|
||||
|
||||
msgid "Engine died unexpectedly"
|
||||
msgstr "Engine died unexpectedly without sending output, possibly due to out of memory: {e}"
|
||||
@@ -30,9 +30,6 @@ msgstr ""
|
||||
"[스페이스 바]\n"
|
||||
"페스"
|
||||
|
||||
msgid "KataGo"
|
||||
msgstr "카타고"
|
||||
|
||||
#. TODO
|
||||
msgid "tab:winrate"
|
||||
msgstr "Win Rate"
|
||||
|
||||
Reference in new issue
Block a user