Русский и английский языки интерфейса
Язык выбирается в шапке панели, а до первого выбора берётся из настроек браузера. Переведены интерфейс, подписи и описания всех параметров конфигов, ошибки API и служебные сообщения менеджера в консоли. Подписи параметров вынесены из app.js в hints-<язык>.json: их больше четырёхсот на язык, и грузить чужой язык незачем. Сообщения менеджера переводятся на выходе из API по словарю, где ключом служит русская фраза из кода, — вывод самого игрового сервера через него проходит без изменений. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/mrleo1nid/pzmanager/internal/i18n"
|
||||
"github.com/mrleo1nid/pzmanager/internal/pzconfig"
|
||||
)
|
||||
|
||||
@@ -24,12 +25,12 @@ func (s *Server) handleGetMods(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"exists": false,
|
||||
"path": path,
|
||||
"hint": "Файл конфигурации появится после первого запуска сервера",
|
||||
"hint": i18n.T(i18n.FromRequest(r), "Файл конфигурации появится после первого запуска сервера"),
|
||||
})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
writeError(w, r, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ func (s *Server) handlePutMods(w http.ResponseWriter, r *http.Request) {
|
||||
path := s.cfg.ServerConfigPath()
|
||||
ini, err := pzconfig.LoadINI(path)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadRequest, "конфиг сервера недоступен: "+err.Error())
|
||||
writeError(w, r, http.StatusBadRequest, "конфиг сервера недоступен: "+err.Error())
|
||||
return
|
||||
}
|
||||
ini.SetMods(body.Mods, body.WorkshopItems)
|
||||
@@ -75,7 +76,7 @@ func (s *Server) handlePutMods(w http.ResponseWriter, r *http.Request) {
|
||||
ini.Set(pzconfig.KeyMap, pzconfig.JoinList(body.Map))
|
||||
}
|
||||
if err := pzconfig.SaveINI(path, ini); err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
writeError(w, r, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
s.sup.AppendLog("manager", "Список модов обновлён. Сервер докачает моды из мастерской при следующем запуске.")
|
||||
@@ -95,7 +96,7 @@ func (s *Server) handleLookupMods(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if len(body.IDs) > 200 {
|
||||
writeError(w, http.StatusBadRequest, "слишком много идентификаторов за один запрос")
|
||||
writeError(w, r, http.StatusBadRequest, "слишком много идентификаторов за один запрос")
|
||||
return
|
||||
}
|
||||
items := s.workshop.Details(r.Context(), body.IDs)
|
||||
@@ -114,13 +115,13 @@ func (s *Server) handleExpandCollection(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
match := idFromInput.FindString(body.ID)
|
||||
if match == "" {
|
||||
writeError(w, http.StatusBadRequest, "не похоже на идентификатор или ссылку на коллекцию")
|
||||
writeError(w, r, http.StatusBadRequest, "не похоже на идентификатор или ссылку на коллекцию")
|
||||
return
|
||||
}
|
||||
|
||||
items, err := s.workshop.Collection(r.Context(), match)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadGateway, err.Error())
|
||||
writeError(w, r, http.StatusBadGateway, err.Error())
|
||||
return
|
||||
}
|
||||
// Названия подтягиваем сразу: иначе панель показала бы десяток голых
|
||||
|
||||
Reference in New Issue
Block a user