mirror of
https://github.com/Cheviiot/Vintner.git
synced 2026-08-03 15:57:24 +00:00
A misconfigured environment (wine missing, msitools not installed, a partially-built toolchain) otherwise only surfaces as a wine-specific error buried deep inside a build. `vintner doctor` checks wine itself (found and actually runs), the optional extraction tools download needs, and every installed <dest>/bin/<arch> toolchain's on-disk layout, printing a pass/fail checklist and exiting non-zero if anything's broken.
231 lines
9.7 KiB
Go
231 lines
9.7 KiB
Go
// Package i18n provides minimal message localization for vintner's own
|
||
// CLI chrome (usage text, progress lines, prompts). It does not localize
|
||
// error messages bubbled up from deeper packages - those stay in English,
|
||
// matching how most cross-platform dev tools keep diagnostic text technical
|
||
// regardless of UI language.
|
||
package i18n
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"strings"
|
||
)
|
||
|
||
type Lang string
|
||
|
||
const (
|
||
EN Lang = "en"
|
||
RU Lang = "ru"
|
||
)
|
||
|
||
var current = detect()
|
||
|
||
// detect picks the active language from VINTNER_LANG (checked first, so
|
||
// it always overrides the locale), falling back to the POSIX locale
|
||
// variables in their usual priority order (LC_ALL, LC_MESSAGES, LANG). Any
|
||
// value starting with "ru" (case-insensitive) selects Russian; anything else
|
||
// falls back to English.
|
||
func detect() Lang {
|
||
for _, key := range []string{"VINTNER_LANG", "LC_ALL", "LC_MESSAGES", "LANG"} {
|
||
v := os.Getenv(key)
|
||
if v == "" {
|
||
continue
|
||
}
|
||
if strings.HasPrefix(strings.ToLower(v), "ru") {
|
||
return RU
|
||
}
|
||
return EN
|
||
}
|
||
return EN
|
||
}
|
||
|
||
// Current returns the active language, for callers that need to branch
|
||
// beyond a simple T() lookup.
|
||
func Current() Lang { return current }
|
||
|
||
// T looks up key in the message catalog and formats it (via fmt.Sprintf)
|
||
// with args, if any. Keys with no translation for the current language fall
|
||
// back to English; keys missing from the catalog entirely are returned
|
||
// as-is, so a missing translation degrades to a visible-but-harmless string
|
||
// rather than a panic.
|
||
func T(key string, args ...any) string {
|
||
msg := key
|
||
if entry, ok := catalog[key]; ok {
|
||
if m, ok := entry[current]; ok {
|
||
msg = m
|
||
} else {
|
||
msg = entry[EN]
|
||
}
|
||
}
|
||
if len(args) == 0 {
|
||
return msg
|
||
}
|
||
return fmt.Sprintf(msg, args...)
|
||
}
|
||
|
||
var catalog = map[string]map[Lang]string{
|
||
"main.usage": {
|
||
EN: `vintner - cross compile with MSVC on Linux via Wine
|
||
|
||
Usage:
|
||
vintner download (dl) --accept-license [--dest <dir>] [options]
|
||
fetch and unpack MSVC/WinSDK/WDK
|
||
vintner install (i) [dir] wire up wrappers for a downloaded MSVC
|
||
vintner env (e) --bin <dir/bin/arch> print INCLUDE/LIB for native clang-cl/lld-link use
|
||
vintner version (v) print the version
|
||
vintner doctor check wine/toolchain setup
|
||
vintner help (h) show this message
|
||
vintner completion bash|zsh print a shell completion script
|
||
|
||
Run "vintner <command> --help" for that command's own options - download
|
||
has many, including --with-wdk, --with-dxsdk, --list-workloads,
|
||
--list-components and --print-deps-tree.
|
||
|
||
--dest/[dir] default to ~/.vintner if omitted.
|
||
Language: set VINTNER_LANG=ru (or LANG=ru_RU...) for Russian output.
|
||
Completion: source <(vintner completion bash) # or zsh
|
||
|
||
Once installed, add <dir>/bin/<arch> to PATH and invoke the tools directly,
|
||
or skip PATH and run them through vintner itself - "vintner cl ...",
|
||
"vintner msbuild ...", etc. (set VINTNER_BIN to a <dir>/bin/<arch> if it's
|
||
not the default ~/.vintner/bin/<host-arch>):
|
||
cl, link, lib, ml, ml64, mc, midl, mt, rc, dumpbin, msbuild, nmake, armasm, armasm64, cmd, findstr
|
||
`,
|
||
RU: `vintner — кросс-компиляция настоящим MSVC на Linux через Wine
|
||
|
||
Использование:
|
||
vintner download (dl) --accept-license [--dest <каталог>] [опции]
|
||
скачать и распаковать MSVC/WinSDK/WDK
|
||
vintner install (i) [каталог] настроить обёртки для скачанного MSVC
|
||
vintner env (e) --bin <dir/bin/arch> вывести INCLUDE/LIB для clang-cl/lld-link напрямую
|
||
vintner version (v) показать версию
|
||
vintner doctor проверить настройку wine/toolchain
|
||
vintner help (h) показать эту справку
|
||
vintner completion bash|zsh вывести скрипт автодополнения для оболочки
|
||
|
||
Запустите «vintner <команда> --help» для параметров конкретной команды —
|
||
у download их много, включая --with-wdk, --with-dxsdk, --list-workloads,
|
||
--list-components и --print-deps-tree.
|
||
|
||
--dest/[каталог] по умолчанию — ~/.vintner.
|
||
Язык: установите VINTNER_LANG=en (или LANG=en_US...) для вывода на английском.
|
||
Можно не трогать PATH: "vintner cl ...", "vintner msbuild ..." и т.д. работают
|
||
напрямую (VINTNER_BIN — если каталог не стандартный ~/.vintner/bin/<hostarch>).
|
||
Автодополнение: source <(vintner completion bash) # или zsh
|
||
|
||
После установки добавьте <dir>/bin/<arch> в PATH и вызывайте инструменты
|
||
напрямую, либо не трогая PATH — «vintner cl ...», «vintner msbuild ...»
|
||
и т.д.:
|
||
cl, link, lib, ml, ml64, mc, midl, mt, rc, dumpbin, msbuild, nmake, armasm, armasm64, cmd, findstr
|
||
`,
|
||
},
|
||
"main.unknown_subcommand": {
|
||
EN: "vintner: unknown subcommand %q\n\n",
|
||
RU: "vintner: неизвестная подкоманда %q\n\n",
|
||
},
|
||
|
||
"install.usage": {
|
||
EN: "usage: vintner install (i) [dest] (default: ~/.vintner)",
|
||
RU: "использование: vintner install (i) [каталог] (по умолчанию: ~/.vintner)",
|
||
},
|
||
"install.default_dir": {
|
||
EN: "No directory given, using default: %s",
|
||
RU: "Каталог не указан, используется значение по умолчанию: %s",
|
||
},
|
||
"install.done": {
|
||
EN: "Done. Add %s to PATH to use cl, link, lib, ... directly, or run them as \"vintner cl\", \"vintner link\", etc. without touching PATH.",
|
||
RU: "Готово. Добавьте %s в PATH, чтобы использовать cl, link, lib и т.д. напрямую, либо запускайте их как «vintner cl», «vintner link» и т.д., не трогая PATH.",
|
||
},
|
||
|
||
"env.usage": {
|
||
EN: "usage: vintner env (e) --bin <dest>/bin/<arch>",
|
||
RU: "использование: vintner env (e) --bin <dest>/bin/<arch>",
|
||
},
|
||
"env.unknown_arch": {
|
||
EN: "vintner env: unknown arch %q\n",
|
||
RU: "vintner env: неизвестная архитектура %q\n",
|
||
},
|
||
|
||
"download.host_arch": {
|
||
EN: "Install packages for %s host architecture",
|
||
RU: "Установка пакетов для архитектуры хоста %s",
|
||
},
|
||
"download.selected": {
|
||
EN: "Selected %d packages, for a total download size of %s, install size of %s\n",
|
||
RU: "Выбрано пакетов: %d, общий размер загрузки %s, размер после установки %s\n",
|
||
},
|
||
"download.default_dest": {
|
||
EN: "--dest not set, using default: %s",
|
||
RU: "--dest не указан, используется значение по умолчанию: %s",
|
||
},
|
||
"download.done": {
|
||
EN: "Done. Next: vintner install %s",
|
||
RU: "Готово. Далее: vintner install %s",
|
||
},
|
||
"download.wdk_skip": {
|
||
EN: "--with-wdk: no x64/arm64 target architecture selected, skipping (no WDK package exists for x86/arm)",
|
||
RU: "--with-wdk: не выбрана целевая архитектура x64/arm64, пропускаем (для x86/arm пакета WDK не существует)",
|
||
},
|
||
"download.wdk_installed": {
|
||
EN: "Installed WDK (%s) %s at %s\n",
|
||
RU: "WDK (%s) %s установлен в %s\n",
|
||
},
|
||
"download.dxsdk_installed": {
|
||
EN: "Installed DirectX SDK (June 2010) at %s\n",
|
||
RU: "DirectX SDK (июнь 2010) установлен в %s\n",
|
||
},
|
||
"download.workloads_header": {
|
||
EN: "Available Workloads (%d):\n",
|
||
RU: "Доступные рабочие нагрузки (Workload) (%d):\n",
|
||
},
|
||
"download.components_header": {
|
||
EN: "Available Components (%d):\n",
|
||
RU: "Доступные компоненты (Component) (%d):\n",
|
||
},
|
||
"download.license_prompt": {
|
||
EN: "Do you accept the license at %s (yes/no)? ",
|
||
RU: "Вы принимаете лицензию по адресу %s (yes/no)? ",
|
||
},
|
||
"download.license_reprompt": {
|
||
EN: "Do you accept the license? Answer \"yes\" or \"no\": ",
|
||
RU: "Вы принимаете лицензию? Ответьте «yes» или «no»: ",
|
||
},
|
||
|
||
"doctor.usage": {
|
||
EN: "usage: vintner doctor",
|
||
RU: "использование: vintner doctor",
|
||
},
|
||
"doctor.section_wine": {
|
||
EN: "Wine:",
|
||
RU: "Wine:",
|
||
},
|
||
"doctor.section_extract": {
|
||
EN: "Extraction tools:",
|
||
RU: "Инструменты распаковки:",
|
||
},
|
||
"doctor.section_toolchain": {
|
||
EN: "Installed toolchain:",
|
||
RU: "Установленный набор инструментов:",
|
||
},
|
||
"doctor.msitools_missing": {
|
||
EN: "msitools: not found (install the msitools package - needed by `vintner download`)",
|
||
RU: "msitools: не найден (установите пакет msitools — нужен для `vintner download`)",
|
||
},
|
||
"doctor.cabextract_missing": {
|
||
EN: "cabextract: not found (install the cabextract package - only needed for --with-wdk/--with-dxsdk)",
|
||
RU: "cabextract: не найден (установите пакет cabextract — нужен только для --with-wdk/--with-dxsdk)",
|
||
},
|
||
"doctor.no_toolchain": {
|
||
EN: "no installed toolchain found under %s (run `vintner download --accept-license && vintner install` first, or set VINTNER_BIN)",
|
||
RU: "установленный набор инструментов не найден в %s (сначала выполните `vintner download --accept-license && vintner install`, либо задайте VINTNER_BIN)",
|
||
},
|
||
"doctor.summary_ok": {
|
||
EN: "\nAll checks passed.",
|
||
RU: "\nВсе проверки пройдены.",
|
||
},
|
||
"doctor.summary_fail": {
|
||
EN: "\nSome checks failed - see [FAIL] lines above.",
|
||
RU: "\nНекоторые проверки не пройдены — см. строки [FAIL] выше.",
|
||
},
|
||
}
|