diff --git a/src/Solver/Solvers.py b/src/Solver/Solvers.py
index 221f1ff4dd028f25f458da81e8028d3fa56303f1..514e06c63eeb998f68520b4c8a3d2209ba6830b5 100644
--- a/src/Solver/Solvers.py
+++ b/src/Solver/Solvers.py
@@ -24,9 +24,9 @@ from Solver.Mage import Mage7, Mage8
 _translate = QCoreApplication.translate
 
 solver_long_name = {
-    "generic": _translate("Solvers", "Generic"),
-    # "mage7": _translate("Solvers", "Mage version 7"),
-    "mage8": _translate("Solvers", "Mage version 8"),
+    "generic": "Generic",
+    # "mage7": "Mage v7",
+    "mage8": "Mage v8",
 }
 
 solver_type_list = {
diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py
index 9fee3a7618be14ccf7bbd19cdc52fc276a468683..94acbe39cd82524bb72a925ba67b4cc5cafe2944 100644
--- a/src/View/MainWindow.py
+++ b/src/View/MainWindow.py
@@ -52,7 +52,7 @@ from View.Stricklers.Window import StricklersWindow
 from View.Frictions.Window import FrictionsWindow
 from View.SedimentLayers.Window import SedimentLayersWindow
 from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
-# from View.SolverParameters.Window import SolverParametersWindow
+from View.SolverParameters.Window import SolverParametersWindow
 # from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
 # from View.CheckList.Window import CheckListWindow
 # from View.Results.Window import ResultsWindow
diff --git a/src/View/SolverParameters/Table.py b/src/View/SolverParameters/Table.py
index 5aa488abacd2dde2293349e75f77f304f10b1d9e..47fa0ae9d8321b5d684a4f121465522d50990f58 100644
--- a/src/View/SolverParameters/Table.py
+++ b/src/View/SolverParameters/Table.py
@@ -34,37 +34,20 @@ from PyQt5.QtWidgets import (
     QComboBox,
 )
 
+from View.Tools.PamhyrTable import PamhyrTableModel
+
 from View.SolverParameters.UndoCommand import *
-from View.SolverParameters import translate as tr
 
 from Solver.Solvers import solver_long_name, solver_type_list
 
-_translate = QCoreApplication.translate
-
-class TableModel(QAbstractTableModel):
-    def __init__(self, data=None, undo=None, tab=""):
-        super(QAbstractTableModel, self).__init__()
-        self._headers = list(tr.table_headers.keys())
-        self._data = data
-        self._undo = undo
-        self._tab = tab
-        self._params = self._data.get_params(self._tab)
-
-    def flags(self, index):
-        options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
-
-        column = index.column()
-
-        if self._headers[column] == "value":
-            options |= Qt.ItemIsEditable
-
-        return options
+logger = logging.getLogger()
 
-    def rowCount(self, parent):
-        return len(self._params)
+_translate = QCoreApplication.translate
 
-    def columnCount(self, parent):
-        return len(self._headers)
+class TableModel(PamhyrTableModel):
+    def _setup_lst(self):
+        self._tab = self._opt_data
+        self._lst = self._data.get_params(self._tab)
 
     def data(self, index, role):
         if role != Qt.ItemDataRole.DisplayRole:
@@ -75,24 +58,18 @@ class TableModel(QAbstractTableModel):
         cname = self._headers[column]
 
         if cname == "name":
-            value = self._params.get(row)[cname]
-            if value in tr.names:
-                value = tr.names[value]
+            value = self._lst.get(row)[cname]
+            if value in self._trad.get_dict("names"):
+                value = self._trad.get_dict("names")[value]
             return value
         elif cname == "value":
-            value = self._params.get(row)[cname]
-            if value in tr.yes_no:
-                value = tr.yes_no[value]
+            value = self._lst.get(row)[cname]
+            if value in self._trad.get_dict("yes_no"):
+                value = self._trad.get_dict("yes_no")[value]
             return value
 
         return QVariant()
 
-    def headerData(self, section, orientation, role):
-        if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
-            return tr.table_headers[self._headers[section]]
-
-        return QVariant()
-
     def setData(self, index, value, role=Qt.EditRole):
         if not index.isValid() or role != Qt.EditRole:
             return False
@@ -102,12 +79,12 @@ class TableModel(QAbstractTableModel):
 
         try:
             if self._headers[column] == "value":
-                if value in tr.r_yes_no:
-                    value = tr.r_yes_no[value].lower()
+                if value in self._trad.get_dict("r_yes_no"):
+                    value = self._trad.get_dict("r_yes_no")[value].lower()
 
                 self._undo.push(
                     SetCommand(
-                        self._params, row,
+                        self._lst, row,
                         "value", value
                     )
                 )
@@ -123,7 +100,7 @@ class TableModel(QAbstractTableModel):
 
     #     self._undo.push(
     #         AddCommand(
-    #             self._params, row
+    #             self._lst, row
     #         )
     #     )
 
@@ -135,7 +112,7 @@ class TableModel(QAbstractTableModel):
 
     #     self._undo.push(
     #         DelCommand(
-    #             self._params, rows
+    #             self._lst, rows
     #         )
     #     )
 
@@ -147,7 +124,7 @@ class TableModel(QAbstractTableModel):
 
     #     self._undo.push(
     #         SortCommand(
-    #             self._params, False
+    #             self._lst, False
     #         )
     #     )
 
@@ -164,7 +141,7 @@ class TableModel(QAbstractTableModel):
 
     #     self._undo_stack.push(
     #         MoveCommand(
-    #             self._params, "up", row
+    #             self._lst, "up", row
     #         )
     #     )
 
@@ -172,7 +149,7 @@ class TableModel(QAbstractTableModel):
     #     self.layoutChanged.emit()
 
     # def move_down(self, index, parent=QModelIndex()):
-    #     if row > len(self._params):
+    #     if row > len(self._lst):
     #         return
 
     #     target = row
@@ -181,7 +158,7 @@ class TableModel(QAbstractTableModel):
 
     #     self._undo_stack.push(
     #         MoveCommand(
-    #             self._params, "down", row
+    #             self._lst, "down", row
     #         )
     #     )
 
diff --git a/src/View/SolverParameters/Window.py b/src/View/SolverParameters/Window.py
index a3b225a6221f34cfc0a9f308281fd8e1a6a79315..b655cd532ba8ae6ed46fd303d093779ba517e532 100644
--- a/src/View/SolverParameters/Window.py
+++ b/src/View/SolverParameters/Window.py
@@ -42,7 +42,7 @@ from PyQt5.QtWidgets import (
 
 from View.SolverParameters.UndoCommand import *
 from View.SolverParameters.Table import TableModel
-from View.SolverParameters import translate as tr
+from View.SolverParameters.translate import ParamTranslate
 
 from Solver.Solvers import solver_long_name, solver_type_list
 
@@ -55,16 +55,13 @@ class SolverParametersWindow(PamhyrWindow):
     _pamhyr_name = "Solver parameters"
 
     def __init__(self, study=None, config=None, parent=None):
-        # Init tanslate dictionary
-        tr.init()
-
         name = self._pamhyr_name + " - " + study.name
-
         super(SolverParametersWindow, self).__init__(
             title = name,
             study = study,
             config = config,
             options = ['copy'],
+            trad = ParamTranslate(),
             parent = parent
         )
 
@@ -73,8 +70,6 @@ class SolverParametersWindow(PamhyrWindow):
         self.setup_sc()
         self.setup_table()
 
-        self.ui.setWindowTitle(self._title)
-
     def setup_sc(self):
         self._undo_stack = {}
 
@@ -101,9 +96,13 @@ class SolverParametersWindow(PamhyrWindow):
 
             # Create table model
             self._table[st] = TableModel(
+                table_view = table,
                 data = self._study.river,
+                opt_data = st,
+                table_headers = self._trad.get_dict("table_headers"),
+                editable_headers = ["value"],
+                trad = self._trad,
                 undo = self._undo_stack[st],
-                tab = st,
             )
 
             table.setModel(self._table[st])
diff --git a/src/View/SolverParameters/translate.py b/src/View/SolverParameters/translate.py
index 2508629ea0ab0cfdeb70d639b7a1bb9174ab4715..01c51a705fd1a91add6e6353a4a1e3d45e136093 100644
--- a/src/View/SolverParameters/translate.py
+++ b/src/View/SolverParameters/translate.py
@@ -18,66 +18,60 @@
 
 from PyQt5.QtCore import QCoreApplication
 
+from View.Tools.PamhyrTranslate import PamhyrTranslate
+
 _translate = QCoreApplication.translate
 
-table_headers = None
-yes_no = None
-r_yes_no = None
-names = None
+class ParamTranslate(PamhyrTranslate):
+    def __init__(self):
+        super(ParamTranslate, self).__init__()
 
-def init():
-    global table_headers
-    table_headers = {
-        "name": _translate("SolverParameters", "Name"),
-        "value": _translate("SolverParameters", "Value")
-    }
+        self._sub_dict["table_headers"] = {
+            "name": _translate("SolverParameters", "Name"),
+            "value": _translate("SolverParameters", "Value")
+        }
 
-    # Used to translate user parameter with value yes or no
-    global yes_no
-    yes_no = {
-        "yes": _translate("SolverParameters", "Yes"),
-        "no": _translate("SolverParameters", "No"),
-        "y": _translate("SolverParameters", "Y"),
-        "n": _translate("SolverParameters", "N"),
-    }
+        self._sub_dict["yes_no"] = {
+            "yes": _translate("SolverParameters", "Yes"),
+            "no": _translate("SolverParameters", "No"),
+            "y": _translate("SolverParameters", "Y"),
+            "n": _translate("SolverParameters", "N"),
+        }
 
-    # Reverse
-    global r_yes_no
-    r_yes_no = {
-        _translate("SolverParameters", "Yes"): "yes",
-        _translate("SolverParameters", "No"): "no",
-        _translate("SolverParameters", "Y"): "y",
-        _translate("SolverParameters", "N"): "n",
-    }
+        self._sub_dict["r_yes_no"] = {
+            _translate("SolverParameters", "Yes"): "yes",
+            _translate("SolverParameters", "No"): "no",
+            _translate("SolverParameters", "Y"): "y",
+            _translate("SolverParameters", "N"): "n",
+        }
 
-    global names
-    names = {
-        "all_init_time": _translate("SolverParameters", "Initial time (jj:hh:mm:ss)"),
-        "all_final_time": _translate("SolverParameters", "Final time (jj:hh:mm:ss)"),
-        "all_timestep": _translate("SolverParameters", "Timestep (second)"),
-        "all_command_line_arguments": _translate("SolverParameters", "Command line arguments"),
-        # Mage specific parameters
-        "mage_min_timestep": _translate("SolverParameters", "Minimum timestep (second)"),
-        "mage_timestep_tra": _translate("SolverParameters", "Time step of writing on .TRA"),
-        "mage_timestep_bin": _translate("SolverParameters", "Time step of writing on .BIN"),
-        "mage_implicitation": _translate("SolverParameters", "Implicitation parameter"),
-        "mage_continuity_discretization": _translate("SolverParameters", "Continuity discretization type (S/L)"),
-        "mage_qsj_discretization": _translate("SolverParameters", "QSJ discretization (A/B)"),
-        "mage_stop_criterion_iterations": _translate("SolverParameters", "Stop criterion iterations (G/A/R)"),
-        "mage_iteration_type": _translate("SolverParameters", "Iteration type"),
-        "mage_smooth_coef": _translate("SolverParameters", "Smoothing coefficient"),
-        "mage_cfl_max": _translate("SolverParameters", "Maximun accepted number of CFL"),
-        "mage_min_height": _translate("SolverParameters", "Minimum water height (meter)"),
-        "mage_max_niter": _translate("SolverParameters", "Maximun number of iterations (< 100)"),
-        "mage_timestep_reduction_factor": _translate("SolverParameters", "Timestep reduction factor"),
-        "mage_precision_reduction_factor_Z": _translate("SolverParameters", "Reduction precision factor of Z"),
-        "mage_precision_reduction_factor_Q": _translate("SolverParameters", "Reduction precision factor of Q"),
-        "mage_precision_reduction_factor_r": _translate("SolverParameters", "Reduction precision factor of residue"),
-        "mage_niter_max_precision": _translate("SolverParameters", "Number of iteration at maximum precision"),
-        "mage_niter_before_switch": _translate("SolverParameters", "Number of iteration before switch"),
-        "mage_max_froude": _translate("SolverParameters", "Maximum accepted Froude number"),
-        "mage_diffluence_node_height_balance": _translate("SolverParameters", "Diffluence node height balance"),
-        "mage_compute_reach_volume_balance": _translate("SolverParameters", "Compute reach volume balance (Y/N)"),
-        "mage_max_reach_volume_balance": _translate("SolverParameters", "Maximum reach volume balance"),
-        "mage_min_reach_volume_to_check": _translate("SolverParameters", "Minimum reach volume to check"),
-    }
+        self._sub_dict["names"] = {
+            "all_init_time": _translate("SolverParameters", "Initial time (jj:hh:mm:ss)"),
+            "all_final_time": _translate("SolverParameters", "Final time (jj:hh:mm:ss)"),
+            "all_timestep": _translate("SolverParameters", "Timestep (second)"),
+            "all_command_line_arguments": _translate("SolverParameters", "Command line arguments"),
+            # Mage specific parameters
+            "mage_min_timestep": _translate("SolverParameters", "Minimum timestep (second)"),
+            "mage_timestep_tra": _translate("SolverParameters", "Time step of writing on .TRA"),
+            "mage_timestep_bin": _translate("SolverParameters", "Time step of writing on .BIN"),
+            "mage_implicitation": _translate("SolverParameters", "Implicitation parameter"),
+            "mage_continuity_discretization": _translate("SolverParameters", "Continuity discretization type (S/L)"),
+            "mage_qsj_discretization": _translate("SolverParameters", "QSJ discretization (A/B)"),
+            "mage_stop_criterion_iterations": _translate("SolverParameters", "Stop criterion iterations (G/A/R)"),
+            "mage_iteration_type": _translate("SolverParameters", "Iteration type"),
+            "mage_smooth_coef": _translate("SolverParameters", "Smoothing coefficient"),
+            "mage_cfl_max": _translate("SolverParameters", "Maximun accepted number of CFL"),
+            "mage_min_height": _translate("SolverParameters", "Minimum water height (meter)"),
+            "mage_max_niter": _translate("SolverParameters", "Maximun number of iterations (< 100)"),
+            "mage_timestep_reduction_factor": _translate("SolverParameters", "Timestep reduction factor"),
+            "mage_precision_reduction_factor_Z": _translate("SolverParameters", "Reduction precision factor of Z"),
+            "mage_precision_reduction_factor_Q": _translate("SolverParameters", "Reduction precision factor of Q"),
+            "mage_precision_reduction_factor_r": _translate("SolverParameters", "Reduction precision factor of residue"),
+            "mage_niter_max_precision": _translate("SolverParameters", "Number of iteration at maximum precision"),
+            "mage_niter_before_switch": _translate("SolverParameters", "Number of iteration before switch"),
+            "mage_max_froude": _translate("SolverParameters", "Maximum accepted Froude number"),
+            "mage_diffluence_node_height_balance": _translate("SolverParameters", "Diffluence node height balance"),
+            "mage_compute_reach_volume_balance": _translate("SolverParameters", "Compute reach volume balance (Y/N)"),
+            "mage_max_reach_volume_balance": _translate("SolverParameters", "Maximum reach volume balance"),
+            "mage_min_reach_volume_to_check": _translate("SolverParameters", "Minimum reach volume to check"),
+        }