A language is a collection of programs. A program is an \emph{abstract syntax tree} (AST), which describes the hierarchy of constructs. An abstract
syntax of a programming language describes the format of abstract syntax trees of programs in this language. Thus, a language is a set of constructive
objects, each of which can be constructively manipulated.
The semantics of a language $\mathscr L$ is a total map
$$
\sembr{\bullet}_{\mathscr L} : \mathscr L \to\mathscr D
$$
where $\mathscr D$ is some \emph{semantic domain}. The choice of the domain is at our command; for example, for Turing-complete languages $\mathscr D$ can
be the set of all partially-recursive (computable) functions.
In reality, the semantics often is described using \emph{interpreters}:
$$
eval : \mathscr L \to\mbox{\lstinline|Input|}\to\mbox{\lstinline|Output|}
$$
where \lstinline|Input| and \lstinline|Output| are sets of (all possible) inputs and outputs for the programs in the language $\mathscr L$. We claim $eval$ to
\forall p \in\mathscr L,\,\forall x\in\mbox{\lstinline|Input|} : \sembr{p}_{\mathscr L}\;x = eval\; p\; x
$$
In other words, an interpreter takes a program and its input as arguments, and returns what the program would return, being run on that
argument. The equality in the definitional property of an interpreter has to be read ``if the right hand side is defined, then the left hand side
is defined, too, and their values coinside'', and vice-versa.
Why interpreters are so important? Because they can be written as programs in a \emph{meta-lanaguge}, or a \mbox{language of implementation}. For example,
if we take ocaml as a language of implementation, then an interpreter of a language $\mathscr L$ is some ocaml program $eval$, such that
$$
\forall p \in\mathscr L,\,\forall x\in\mbox{\lstinline|Input|} : \sembr{p}_{\mathscr L}\;x = \sembr{eval}_{\mbox{ocaml}}\; p\; x
$$
How to define $\sembr{\bullet}_{\mbox{ocaml}}$? We can write an interpreter in some other language. Thus, a \emph{tower} of meta-languages and interpreters
comes into consideration. When to stop? When the meta-language is simple enough for intuitive understanding (in reality: some math-based frameworks like
operational, denotational or game semantics, etc.)
Pragmatically: if you have a good implementation of a good programming language you trust, you can write interpreters of other languages.