From 18e9adabaaf0607410ea269374ee25418941c33c Mon Sep 17 00:00:00 2001 From: Milan Nikolic Date: Thu, 25 Jun 2026 21:52:23 +0200 Subject: [PATCH] Add i18n --- cmd/cbconvert-gui/dialogs.go | 6 +- cmd/cbconvert-gui/handlers.go | 24 +-- cmd/cbconvert-gui/i18n/detect_unix.go | 26 ++++ cmd/cbconvert-gui/i18n/detect_windows.go | 26 ++++ cmd/cbconvert-gui/i18n/i18n.go | 189 +++++++++++++++++++++++ cmd/cbconvert-gui/i18n/i18n_cs.go | 128 +++++++++++++++ cmd/cbconvert-gui/i18n/i18n_de.go | 128 +++++++++++++++ cmd/cbconvert-gui/i18n/i18n_en.go | 128 +++++++++++++++ cmd/cbconvert-gui/i18n/i18n_es.go | 128 +++++++++++++++ cmd/cbconvert-gui/i18n/i18n_fr.go | 128 +++++++++++++++ cmd/cbconvert-gui/i18n/i18n_it.go | 128 +++++++++++++++ cmd/cbconvert-gui/i18n/i18n_ja.go | 128 +++++++++++++++ cmd/cbconvert-gui/i18n/i18n_pt.go | 128 +++++++++++++++ cmd/cbconvert-gui/i18n/i18n_ru.go | 128 +++++++++++++++ cmd/cbconvert-gui/i18n/i18n_zh.go | 128 +++++++++++++++ cmd/cbconvert-gui/main.go | 5 + cmd/cbconvert-gui/options.go | 3 +- cmd/cbconvert-gui/settings.go | 5 +- cmd/cbconvert-gui/state.go | 25 +-- cmd/cbconvert-gui/widgets.go | 177 ++++++++++----------- 20 files changed, 1653 insertions(+), 113 deletions(-) create mode 100644 cmd/cbconvert-gui/i18n/detect_unix.go create mode 100644 cmd/cbconvert-gui/i18n/detect_windows.go create mode 100644 cmd/cbconvert-gui/i18n/i18n.go create mode 100644 cmd/cbconvert-gui/i18n/i18n_cs.go create mode 100644 cmd/cbconvert-gui/i18n/i18n_de.go create mode 100644 cmd/cbconvert-gui/i18n/i18n_en.go create mode 100644 cmd/cbconvert-gui/i18n/i18n_es.go create mode 100644 cmd/cbconvert-gui/i18n/i18n_fr.go create mode 100644 cmd/cbconvert-gui/i18n/i18n_it.go create mode 100644 cmd/cbconvert-gui/i18n/i18n_ja.go create mode 100644 cmd/cbconvert-gui/i18n/i18n_pt.go create mode 100644 cmd/cbconvert-gui/i18n/i18n_ru.go create mode 100644 cmd/cbconvert-gui/i18n/i18n_zh.go diff --git a/cmd/cbconvert-gui/dialogs.go b/cmd/cbconvert-gui/dialogs.go index 8baef0c..23c84e6 100644 --- a/cmd/cbconvert-gui/dialogs.go +++ b/cmd/cbconvert-gui/dialogs.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/gen2brain/cbconvert" + "github.com/gen2brain/cbconvert/cmd/cbconvert-gui/i18n" "github.com/gen2brain/iup-go/iup" ) @@ -98,8 +99,9 @@ func previewCover() iup.FileFunc { iup.DrawImage(ih, dlgPreviewName, (cw-iw)/2, (ch-iih)/2, iw, iih) } else { ih.SetAttribute("DRAWCOLOR", "128 128 128") - tw, th := iup.DrawGetTextSize(ih, "No preview") - iup.DrawText(ih, "No preview", (cw-tw)/2, (ch-th)/2, 0, 0) + noPreview := i18n.Str(i18n.NoPreview) + tw, th := iup.DrawGetTextSize(ih, noPreview) + iup.DrawText(ih, noPreview, (cw-tw)/2, (ch-th)/2, 0, 0) } iup.DrawEnd(ih) diff --git a/cmd/cbconvert-gui/handlers.go b/cmd/cbconvert-gui/handlers.go index 1c053ee..848a260 100644 --- a/cmd/cbconvert-gui/handlers.go +++ b/cmd/cbconvert-gui/handlers.go @@ -11,7 +11,9 @@ import ( "strconv" "github.com/fvbommel/sortorder" + "github.com/gen2brain/cbconvert" + "github.com/gen2brain/cbconvert/cmd/cbconvert-gui/i18n" "github.com/gen2brain/iup-go/iup" ) @@ -196,7 +198,7 @@ func onPageChanged() int { } func onAddFiles(ih iup.Ihandle) int { - args, err := fileDlg("Add Files", true, false, inputDirKey) + args, err := fileDlg(i18n.Lng(i18n.DlgAddFiles), true, false, inputDirKey) if err != nil { iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) fmt.Println(err) @@ -222,7 +224,7 @@ func onAddFiles(ih iup.Ihandle) int { } func onAddDir(ih iup.Ihandle) int { - args, err := fileDlg("Add Directory", false, true, inputDirKey) + args, err := fileDlg(i18n.Lng(i18n.DlgAddDir), false, true, inputDirKey) if err != nil { iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) fmt.Println(err) @@ -459,7 +461,7 @@ func onConvert(ih iup.Ihandle) int { } func onOutputDirectory(ih iup.Ihandle) int { - args, err := fileDlg("Output Directory", false, true, outputDirKey) + args, err := fileDlg(i18n.Lng(i18n.DlgOutputDir), false, true, outputDirKey) if err != nil { iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) fmt.Println(err) @@ -477,7 +479,7 @@ func onOutputDirectory(ih iup.Ihandle) int { } func onOutputFile(ih iup.Ihandle) int { - name := saveDlg("Output File", outputDirKey) + name := saveDlg(i18n.Lng(i18n.DlgOutputFile), outputDirKey) if name != "" { iup.GetHandle("OutFile").SetAttribute("VALUE", filepath.Base(name)) iup.GetHandle("OutDir").SetAttribute("VALUE", filepath.Dir(name)) @@ -490,19 +492,19 @@ func onOutputFile(ih iup.Ihandle) int { func onFilterChanged(ih iup.Ihandle) int { switch ih.GetInt("VALUE") { case 1: - ih.SetAttribute("TIP", "NearestNeighbor is the fastest resampling filter, no antialiasing") + ih.SetAttribute("TIP", i18n.Lng(i18n.FilterNearest)) case 2: - ih.SetAttribute("TIP", "Box filter (averaging pixels)") + ih.SetAttribute("TIP", i18n.Lng(i18n.FilterBox)) case 3: - ih.SetAttribute("TIP", "Linear is the bilinear filter, smooth and reasonably fast") + ih.SetAttribute("TIP", i18n.Lng(i18n.FilterLinear)) case 4: - ih.SetAttribute("TIP", "MitchellNetravali is a smooth bicubic filter") + ih.SetAttribute("TIP", i18n.Lng(i18n.FilterMitchell)) case 5: - ih.SetAttribute("TIP", "CatmullRom is a sharp bicubic filter") + ih.SetAttribute("TIP", i18n.Lng(i18n.FilterCatmull)) case 6: - ih.SetAttribute("TIP", "Gaussian is a blurring filter that uses gaussian function, useful for noise removal") + ih.SetAttribute("TIP", i18n.Lng(i18n.FilterGaussian)) case 7: - ih.SetAttribute("TIP", "Lanczos is a high-quality resampling filter, it's slower than cubic filters") + ih.SetAttribute("TIP", i18n.Lng(i18n.FilterLanczos)) } previewPost() diff --git a/cmd/cbconvert-gui/i18n/detect_unix.go b/cmd/cbconvert-gui/i18n/detect_unix.go new file mode 100644 index 0000000..2b83736 --- /dev/null +++ b/cmd/cbconvert-gui/i18n/detect_unix.go @@ -0,0 +1,26 @@ +//go:build !windows + +package i18n + +import ( + "os" + "strings" +) + +// systemLangCode returns the two-letter language code from the POSIX locale environment, or "". +func systemLangCode() string { + for _, env := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} { + v := os.Getenv(env) + if v == "" || v == "C" || v == "POSIX" { + continue + } + + if i := strings.IndexAny(v, "_.@"); i >= 0 { + v = v[:i] + } + + return strings.ToLower(v) + } + + return "" +} diff --git a/cmd/cbconvert-gui/i18n/detect_windows.go b/cmd/cbconvert-gui/i18n/detect_windows.go new file mode 100644 index 0000000..e28b023 --- /dev/null +++ b/cmd/cbconvert-gui/i18n/detect_windows.go @@ -0,0 +1,26 @@ +//go:build windows + +package i18n + +import "syscall" + +// primaryLang maps a Windows primary-language id to a two-letter language code. +var primaryLang = map[uint16]string{ + 0x09: "en", + 0x16: "pt", + 0x0a: "es", + 0x05: "cs", + 0x19: "ru", + 0x07: "de", + 0x0c: "fr", + 0x04: "zh", + 0x11: "ja", + 0x10: "it", +} + +// systemLangCode returns the two-letter code of the user's default UI language, or "". +func systemLangCode() string { + r, _, _ := syscall.NewLazyDLL("kernel32.dll").NewProc("GetUserDefaultUILanguage").Call() + + return primaryLang[uint16(r)&0x3ff] +} diff --git a/cmd/cbconvert-gui/i18n/i18n.go b/cmd/cbconvert-gui/i18n/i18n.go new file mode 100644 index 0000000..fb9abf5 --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n.go @@ -0,0 +1,189 @@ +// Package i18n holds the cbconvert GUI message keys and per-language string packs. +package i18n + +import "github.com/gen2brain/iup-go/iup" + +const ( + ColTitle = "COL_TITLE" + ColType = "COL_TYPE" + ColSize = "COL_SIZE" + + TabInput = "TAB_INPUT" + TabOutput = "TAB_OUTPUT" + TabImage = "TAB_IMAGE" + TabTransform = "TAB_TRANSFORM" + + LblPage = "LBL_PAGE" + TipPage = "TIP_PAGE" + + TglRecursive = "TGL_RECURSIVE" + TipRecursive = "TIP_RECURSIVE" + TglNoRGB = "TGL_NORGB" + TipNoRGB = "TIP_NORGB" + TglNoCover = "TGL_NOCOVER" + TipNoCover = "TIP_NOCOVER" + TglNoNonImage = "TGL_NONONIMAGE" + TipNoNonImage = "TIP_NONONIMAGE" + TglNoConvert = "TGL_NOCONVERT" + TipNoConvert = "TIP_NOCONVERT" + LblMinSize = "LBL_MINSIZE" + TipSize = "TIP_SIZE" + LblDPI = "LBL_DPI" + TipDPI = "TIP_DPI" + + LblOutDir = "LBL_OUTDIR" + TipOutDir = "TIP_OUTDIR" + BtnBrowse = "BTN_BROWSE" + LblSuffix = "LBL_SUFFIX" + TipSuffix = "TIP_SUFFIX" + LblArchive = "LBL_ARCHIVE" + TipArchive = "TIP_ARCHIVE" + LblCompression = "LBL_COMPRESSION" + TipZipLevel = "TIP_ZIPLEVEL" + TglCombine = "TGL_COMBINE" + TipCombine = "TIP_COMBINE" + LblOutFile = "LBL_OUTFILE" + TipOutFile = "TIP_OUTFILE" + + LblFormat = "LBL_FORMAT" + TipFormat = "TIP_FORMAT" + LblSize = "LBL_SIZE" + CueWidth = "CUE_WIDTH" + CueHeight = "CUE_HEIGHT" + TipWidthHeight = "TIP_WIDTHHEIGHT" + TglFit = "TGL_FIT" + TipFit = "TIP_FIT" + TglNoUpscale = "TGL_NOUPSCALE" + TipNoUpscale = "TIP_NOUPSCALE" + LblFilter = "LBL_FILTER" + LblQuality = "LBL_QUALITY" + TipQuality = "TIP_QUALITY" + LblEffort = "LBL_EFFORT" + TipEffort = "TIP_EFFORT" + TglLossless = "TGL_LOSSLESS" + TipLossless = "TIP_LOSSLESS" + TglGrayscale = "TGL_GRAYSCALE" + TipGrayscale = "TIP_GRAYSCALE" + + LblBrightness = "LBL_BRIGHTNESS" + TipBrightness = "TIP_BRIGHTNESS" + LblContrast = "LBL_CONTRAST" + TipContrast = "TIP_CONTRAST" + LblRotate = "LBL_ROTATE" + TipRotate = "TIP_ROTATE" + + EffortMethod = "EFFORT_METHOD" + EffortSpeed = "EFFORT_SPEED" + EffortEffort = "EFFORT_EFFORT" + TipEffortWebp = "TIP_EFFORT_WEBP" + TipEffortAvif = "TIP_EFFORT_AVIF" + TipEffortJxl = "TIP_EFFORT_JXL" + + BtnAddFiles = "BTN_ADDFILES" + BtnAddDir = "BTN_ADDDIR" + BtnRemove = "BTN_REMOVE" + BtnRemoveAll = "BTN_REMOVEALL" + BtnThumbnail = "BTN_THUMBNAIL" + BtnCover = "BTN_COVER" + BtnConvert = "BTN_CONVERT" + BtnCancel = "BTN_CANCEL" + TipCancel = "TIP_CANCEL" + BtnReset = "BTN_RESET" + TipReset = "TIP_RESET" + BtnSave = "BTN_SAVE" + TipSave = "TIP_SAVE" + BtnCommand = "BTN_COMMAND" + TipCommand = "TIP_COMMAND" + LblProfile = "LBL_PROFILE" + TipProfile = "TIP_PROFILE" + + TipThumbnail = "TIP_THUMBNAIL" + TipCover = "TIP_COVER" + TipConvert = "TIP_CONVERT" + + StatusNeedFilesAndDir = "STATUS_NEED_FILES_AND_DIR" + StatusNeedFiles = "STATUS_NEED_FILES" + StatusNeedOutDir = "STATUS_NEED_OUTDIR" + StatusFileOf = "STATUS_FILE_OF" + + FilterNearest = "FILTER_NEAREST" + FilterBox = "FILTER_BOX" + FilterLinear = "FILTER_LINEAR" + FilterMitchell = "FILTER_MITCHELL" + FilterCatmull = "FILTER_CATMULL" + FilterGaussian = "FILTER_GAUSSIAN" + FilterLanczos = "FILTER_LANCZOS" + + DlgAddFiles = "DLG_ADDFILES" + DlgAddDir = "DLG_ADDDIR" + DlgOutputDir = "DLG_OUTPUTDIR" + DlgOutputFile = "DLG_OUTPUTFILE" + DlgCommandLine = "DLG_COMMANDLINE" + DlgSaveProfile = "DLG_SAVEPROFILE" + + ParamName = "PARAM_NAME" + MsgInvalidNameTitle = "MSG_INVALIDNAME_TITLE" + MsgInvalidNameBody = "MSG_INVALIDNAME_BODY" + + NoPreview = "NO_PREVIEW" +) + +// packs maps an IUP language name to its message pack, filled by each language file's init. +var packs = map[string]map[string]string{} + +// register adds a language pack; called from each i18n_.go init. +func register(lang string, pack map[string]string) { + packs[lang] = pack +} + +// langByCode maps a two-letter language code to the IUP language name. +var langByCode = map[string]string{ + "en": "ENGLISH", + "pt": "PORTUGUESE", + "es": "SPANISH", + "cs": "CZECH", + "ru": "RUSSIAN", + "de": "GERMAN", + "fr": "FRENCH", + "zh": "CHINESE", + "ja": "JAPANESE", + "it": "ITALIAN", +} + +// Lng wraps a message key for IUP's automatic language-string lookup. +func Lng(key string) string { + return "_@" + key +} + +// Str returns the translated string for a key, for use where IUP's "_@" prefix does not apply. +func Str(key string) string { + return iup.GetLanguageString(key) +} + +// Init detects the system language, switches IUP's predefined strings to it, and registers the message packs. +func Init() { + lang := detect() + iup.SetLanguage(lang) + + registerPack(packs["ENGLISH"]) + if lang != "ENGLISH" { + if pack, ok := packs[lang]; ok { + registerPack(pack) + } + } +} + +func registerPack(pack map[string]string) { + for name, value := range pack { + iup.SetLanguageString(name, value) + } +} + +// detect returns the IUP language name for the system locale, or ENGLISH. +func detect() string { + if name, ok := langByCode[systemLangCode()]; ok { + return name + } + + return "ENGLISH" +} diff --git a/cmd/cbconvert-gui/i18n/i18n_cs.go b/cmd/cbconvert-gui/i18n/i18n_cs.go new file mode 100644 index 0000000..80eba35 --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n_cs.go @@ -0,0 +1,128 @@ +package i18n + +func init() { + register("CZECH", map[string]string{ + ColTitle: "Název", + ColType: "Typ", + ColSize: "Velikost (MiB)", + + TabInput: "Vstup", + TabOutput: "Výstup", + TabImage: "Obrázek", + TabTransform: "Transformace", + + LblPage: "Stránka:", + TipPage: "Náhled jiné stránky vybraného komiksu", + + TglRecursive: " Procházet podadresáře", + TipRecursive: "Zpracovat podadresáře rekurzivně", + TglNoRGB: " Pouze obrázky ve stupních šedi", + TipNoRGB: "Nepřevádět obrázky s barevným prostorem RGB", + TglNoCover: " Vyloučit obálku", + TipNoCover: "Nepřevádět obrázek obálky", + TglNoNonImage: " Odstranit z archivu soubory, které nejsou obrázky", + TipNoNonImage: "Odstranit z archivu soubory .nfo, .xml, .txt", + TglNoConvert: " Netransformovat ani nepřevádět obrázky", + TipNoConvert: "Kopírovat obrázky z archivu nebo adresáře beze změn", + LblMinSize: "Minimální velikost (MiB):", + TipSize: "Zpracovat pouze soubory větší než minimální velikost", + LblDPI: "DPI dokumentu:", + TipDPI: "Rozlišení pro vykreslování dokumentů (PDF, EPUB atd.); výchozí je 300", + + LblOutDir: "Výstupní adresář:", + TipOutDir: "Adresář, do kterého se zapisují převedené soubory (povinné)", + BtnBrowse: "Procházet...", + LblSuffix: "Přidat příponu k výstupnímu souboru:", + TipSuffix: "Přidat příponu k názvu souboru, např. nazevsouboru_pripona.cbz", + LblArchive: "Formát archivu:", + TipArchive: "Výstupní kontejner: ZIP (.cbz) nebo nekomprimovaný TAR (.cbt)", + LblCompression: "Komprese:", + TipZipLevel: "Komprese ZIP: Uložit ji vypne, 1 je nejrychlejší, 9 nejmenší", + TglCombine: " Sloučit do jednoho souboru", + TipCombine: "Sloučit všechny uvedené soubory do jednoho archivu", + LblOutFile: "Výstupní soubor:", + TipOutFile: "Název sloučeného souboru (výchozí: první vstup + -combined)", + + LblFormat: "Formát:", + TipFormat: "Výstupní formát obrázku pro převedené stránky", + LblSize: "Velikost:", + CueWidth: "šířka", + CueHeight: "výška", + TipWidthHeight: "Pokud není nastavena šířka nebo výška, zachová se poměr stran obrázku", + TglFit: " Nejlepší přizpůsobení", + TipFit: "Nejlepší přizpůsobení požadované šířce a výšce", + TglNoUpscale: " Nezvětšovat", + TipNoUpscale: "Nezvětšovat obrázky, které jsou již menší než požadovaná velikost", + LblFilter: "Filtr změny velikosti:", + LblQuality: "Kvalita: ", + TipQuality: "Kvalita ovlivňuje JPEG, WEBP, AVIF a JXL", + LblEffort: "Úsilí:", + TipEffort: "Rychlost/úsilí kodéru (WEBP, AVIF, JXL)", + TglLossless: " Bezztrátový", + TipLossless: "Bezztrátová komprese (WEBP, AVIF, JXL), ignoruje kvalitu", + TglGrayscale: " Stupně šedi", + TipGrayscale: "Převést obrázky do stupňů šedi (monochromaticky)", + + LblBrightness: "Jas: ", + TipBrightness: "Upravit jas obrázků", + LblContrast: "Kontrast: ", + TipContrast: "Upravit kontrast obrázků", + LblRotate: "Otočit:", + TipRotate: "Otočit každou stránku po směru hodinových ručiček o zadaný úhel ve stupních", + + EffortMethod: "Metoda", + EffortSpeed: "Rychlost", + EffortEffort: "Úsilí", + TipEffortWebp: "Metoda WEBP, vyšší je lepší/pomalejší (0-6, výchozí 4)", + TipEffortAvif: "Rychlost AVIF, vyšší je rychlejší/horší (0-10, výchozí 10)", + TipEffortJxl: "Úsilí JXL, vyšší je lepší/pomalejší (1-10, výchozí 7)", + + BtnAddFiles: "Přidat &soubory...", + BtnAddDir: "Přidat &adresář...", + BtnRemove: "Odebrat", + BtnRemoveAll: "Odebrat vše", + BtnThumbnail: "Náhled", + BtnCover: "Obálka", + BtnConvert: "&Převést", + BtnCancel: "Zrušit", + TipCancel: "Zrušit probíhající operaci (nebo stisknout Esc)", + BtnReset: "Obnovit", + TipReset: "Obnovit všechna nastavení na výchozí hodnoty", + BtnSave: "Uložit", + TipSave: "Uložit aktuální nastavení do profilu", + BtnCommand: "Příkaz", + TipCommand: "Zobrazit odpovídající příkazový řádek", + LblProfile: "Profil:", + TipProfile: "Vybrat profil nastavení", + + TipThumbnail: "Extrahovat náhledy obálek", + TipCover: "Extrahovat obálky", + TipConvert: "Převést soubory do vybraného formátu", + + StatusNeedFilesAndDir: "Přidejte soubory a nastavte výstupní adresář", + StatusNeedFiles: "Přidejte soubory", + StatusNeedOutDir: "Nastavte výstupní adresář", + StatusFileOf: "Soubor %d z %d", + + FilterNearest: "NearestNeighbor je nejrychlejší převzorkovací filtr, bez vyhlazování", + FilterBox: "Filtr Box (průměrování pixelů)", + FilterLinear: "Linear je bilineární filtr, hladký a přiměřeně rychlý", + FilterMitchell: "MitchellNetravali je hladký bikubický filtr", + FilterCatmull: "CatmullRom je ostrý bikubický filtr", + FilterGaussian: "Gaussian je rozostřovací filtr využívající Gaussovu funkci, užitečný pro odstranění šumu", + FilterLanczos: "Lanczos je vysoce kvalitní převzorkovací filtr, pomalejší než bikubické filtry", + + DlgAddFiles: "Přidat soubory", + DlgAddDir: "Přidat adresář", + DlgOutputDir: "Výstupní adresář", + DlgOutputFile: "Výstupní soubor", + DlgCommandLine: "Příkazový řádek", + DlgSaveProfile: "Uložit profil", + + ParamName: "Název: %s\n", + MsgInvalidNameTitle: "Neplatný název", + MsgInvalidNameBody: "Název profilu nesmí být prázdný ani obsahovat '.' nebo ';'.", + + NoPreview: "Žádný náhled", + }) +} diff --git a/cmd/cbconvert-gui/i18n/i18n_de.go b/cmd/cbconvert-gui/i18n/i18n_de.go new file mode 100644 index 0000000..0a2ff63 --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n_de.go @@ -0,0 +1,128 @@ +package i18n + +func init() { + register("GERMAN", map[string]string{ + ColTitle: "Titel", + ColType: "Typ", + ColSize: "Größe (MiB)", + + TabInput: "Eingabe", + TabOutput: "Ausgabe", + TabImage: "Bild", + TabTransform: "Transformation", + + LblPage: "Seite:", + TipPage: "Eine andere Seite des ausgewählten Comics als Vorschau anzeigen", + + TglRecursive: " Unterverzeichnisse rekursiv", + TipRecursive: "Unterverzeichnisse rekursiv verarbeiten", + TglNoRGB: " Nur Graustufenbilder", + TipNoRGB: "Bilder mit RGB-Farbraum nicht konvertieren", + TglNoCover: " Titelbild ausschließen", + TipNoCover: "Das Titelbild nicht konvertieren", + TglNoNonImage: " Nicht-Bilddateien aus dem Archiv entfernen", + TipNoNonImage: ".nfo-, .xml-, .txt-Dateien aus dem Archiv entfernen", + TglNoConvert: " Bilder nicht transformieren oder konvertieren", + TipNoConvert: "Bilder aus Archiv oder Verzeichnis ohne Änderungen kopieren", + LblMinSize: "Mindestgröße (MiB):", + TipSize: "Nur Dateien größer als die Mindestgröße verarbeiten", + LblDPI: "Dokument-DPI:", + TipDPI: "Auflösung zum Rendern von Dokumenten (PDF, EPUB usw.); Standard ist 300", + + LblOutDir: "Ausgabeverzeichnis:", + TipOutDir: "Verzeichnis, in das konvertierte Dateien geschrieben werden (erforderlich)", + BtnBrowse: "Durchsuchen...", + LblSuffix: "Suffix an Ausgabedatei anhängen:", + TipSuffix: "Suffix an den Dateinamen anhängen, z. B. dateiname_suffix.cbz", + LblArchive: "Archivformat:", + TipArchive: "Ausgabecontainer: ZIP (.cbz) oder unkomprimiertes TAR (.cbt)", + LblCompression: "Komprimierung:", + TipZipLevel: "ZIP-Komprimierung: Speichern deaktiviert sie, 1 ist am schnellsten, 9 am kleinsten", + TglCombine: " In einer Datei zusammenfassen", + TipCombine: "Alle aufgelisteten Dateien zu einem Archiv zusammenführen", + LblOutFile: "Ausgabedatei:", + TipOutFile: "Name der zusammengefassten Datei (Standard: erste Eingabe + -combined)", + + LblFormat: "Format:", + TipFormat: "Ausgabebildformat für die konvertierten Seiten", + LblSize: "Größe:", + CueWidth: "Breite", + CueHeight: "Höhe", + TipWidthHeight: "Wenn Breite oder Höhe nicht gesetzt ist, bleibt das Seitenverhältnis erhalten", + TglFit: " Optimale Anpassung", + TipFit: "Optimale Anpassung an gewünschte Breite und Höhe", + TglNoUpscale: " Nicht vergrößern", + TipNoUpscale: "Bilder, die bereits kleiner als die gewünschte Größe sind, nicht vergrößern", + LblFilter: "Skalierungsfilter:", + LblQuality: "Qualität: ", + TipQuality: "Qualität betrifft JPEG, WEBP, AVIF und JXL", + LblEffort: "Aufwand:", + TipEffort: "Encoder-Geschwindigkeit/-Aufwand (WEBP, AVIF, JXL)", + TglLossless: " Verlustfrei", + TipLossless: "Verlustfreie Komprimierung (WEBP, AVIF, JXL), ignoriert Qualität", + TglGrayscale: " Graustufen", + TipGrayscale: "Bilder in Graustufen umwandeln (monochrom)", + + LblBrightness: "Helligkeit: ", + TipBrightness: "Die Helligkeit der Bilder anpassen", + LblContrast: "Kontrast: ", + TipContrast: "Den Kontrast der Bilder anpassen", + LblRotate: "Drehen:", + TipRotate: "Jede Seite um den angegebenen Winkel im Uhrzeigersinn drehen", + + EffortMethod: "Methode", + EffortSpeed: "Geschwindigkeit", + EffortEffort: "Aufwand", + TipEffortWebp: "WEBP-Methode, höher ist besser/langsamer (0-6, Standard 4)", + TipEffortAvif: "AVIF-Geschwindigkeit, höher ist schneller/schlechter (0-10, Standard 10)", + TipEffortJxl: "JXL-Aufwand, höher ist besser/langsamer (1-10, Standard 7)", + + BtnAddFiles: "&Dateien hinzufügen...", + BtnAddDir: "&Verzeichnis hinzufügen...", + BtnRemove: "Entfernen", + BtnRemoveAll: "Alle entfernen", + BtnThumbnail: "Miniaturbild", + BtnCover: "Titelbild", + BtnConvert: "&Konvertieren", + BtnCancel: "Abbrechen", + TipCancel: "Laufenden Vorgang abbrechen (oder Esc drücken)", + BtnReset: "Zurücksetzen", + TipReset: "Alle Einstellungen auf die Standardwerte zurücksetzen", + BtnSave: "Speichern", + TipSave: "Aktuelle Einstellungen in einem Profil speichern", + BtnCommand: "Befehl", + TipCommand: "Die entsprechende Befehlszeile anzeigen", + LblProfile: "Profil:", + TipProfile: "Ein Einstellungsprofil auswählen", + + TipThumbnail: "Titelbild-Miniaturen extrahieren", + TipCover: "Titelbilder extrahieren", + TipConvert: "Dateien in das ausgewählte Format konvertieren", + + StatusNeedFilesAndDir: "Dateien hinzufügen und Ausgabeverzeichnis festlegen", + StatusNeedFiles: "Dateien hinzufügen", + StatusNeedOutDir: "Ausgabeverzeichnis festlegen", + StatusFileOf: "Datei %d von %d", + + FilterNearest: "NearestNeighbor ist der schnellste Skalierungsfilter, ohne Antialiasing", + FilterBox: "Box-Filter (Mittelung der Pixel)", + FilterLinear: "Linear ist der bilineare Filter, glatt und einigermaßen schnell", + FilterMitchell: "MitchellNetravali ist ein glatter bikubischer Filter", + FilterCatmull: "CatmullRom ist ein scharfer bikubischer Filter", + FilterGaussian: "Gaussian ist ein Weichzeichnungsfilter mit Gauß-Funktion, nützlich zur Rauschentfernung", + FilterLanczos: "Lanczos ist ein hochwertiger Skalierungsfilter, langsamer als bikubische Filter", + + DlgAddFiles: "Dateien hinzufügen", + DlgAddDir: "Verzeichnis hinzufügen", + DlgOutputDir: "Ausgabeverzeichnis", + DlgOutputFile: "Ausgabedatei", + DlgCommandLine: "Befehlszeile", + DlgSaveProfile: "Profil speichern", + + ParamName: "Name: %s\n", + MsgInvalidNameTitle: "Ungültiger Name", + MsgInvalidNameBody: "Der Profilname darf nicht leer sein oder '.' oder ';' enthalten.", + + NoPreview: "Keine Vorschau", + }) +} diff --git a/cmd/cbconvert-gui/i18n/i18n_en.go b/cmd/cbconvert-gui/i18n/i18n_en.go new file mode 100644 index 0000000..7fd157f --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n_en.go @@ -0,0 +1,128 @@ +package i18n + +func init() { + register("ENGLISH", map[string]string{ + ColTitle: "Title", + ColType: "Type", + ColSize: "Size (MiB)", + + TabInput: "Input", + TabOutput: "Output", + TabImage: "Image", + TabTransform: "Transform", + + LblPage: "Page:", + TipPage: "Preview a different page of the selected comic", + + TglRecursive: " Recurse SubDirectories", + TipRecursive: "Process subdirectories recursively", + TglNoRGB: " Only Grayscale Images", + TipNoRGB: "Do not convert images that have RGB colorspace", + TglNoCover: " Exclude Cover", + TipNoCover: "Do not convert the cover image", + TglNoNonImage: " Remove Non-Image Files from the Archive", + TipNoNonImage: "Remove .nfo, .xml, .txt files from the archive", + TglNoConvert: " Do not Transform or Convert Images", + TipNoConvert: "Copy images from archive or directory without modifications", + LblMinSize: "Minimum Size (MiB):", + TipSize: "Process only files larger than minimum size", + LblDPI: "Document DPI:", + TipDPI: "Resolution for rendering documents (PDF, EPUB, etc.); Default is 300", + + LblOutDir: "Output Directory:", + TipOutDir: "Directory where converted files are written (required)", + BtnBrowse: "Browse...", + LblSuffix: "Add Suffix to Output File:", + TipSuffix: "Add suffix to filename, i.e. filename_suffix.cbz", + LblArchive: "Archive Format:", + TipArchive: "Output container: ZIP (.cbz) or uncompressed TAR (.cbt)", + LblCompression: "Compression:", + TipZipLevel: "ZIP compression: Store disables it, 1 is fastest, 9 is smallest", + TglCombine: " Combine into single file", + TipCombine: "Merge all listed files into one archive", + LblOutFile: "Output File:", + TipOutFile: "Combined file name (default: first input + -combined)", + + LblFormat: "Format:", + TipFormat: "Output image format for the converted pages", + LblSize: "Size:", + CueWidth: "width", + CueHeight: "height", + TipWidthHeight: "If one of, width or height is not set, the image aspect ratio is preserved", + TglFit: " Best Fit", + TipFit: "Best fit for required width and height", + TglNoUpscale: " No Upscale", + TipNoUpscale: "Do not enlarge images already smaller than the requested size", + LblFilter: "Resize Filter:", + LblQuality: "Quality: ", + TipQuality: "Quality affects JPEG, WEBP, AVIF and JXL", + LblEffort: "Effort:", + TipEffort: "Encoder speed/effort (WEBP, AVIF, JXL)", + TglLossless: " Lossless", + TipLossless: "Lossless compression (WEBP, AVIF, JXL), ignores quality", + TglGrayscale: " Grayscale", + TipGrayscale: "Convert images to grayscale (monochromatic)", + + LblBrightness: "Brightness: ", + TipBrightness: "Adjust the brightness of the images", + LblContrast: "Contrast: ", + TipContrast: "Adjust the contrast of the images", + LblRotate: "Rotate:", + TipRotate: "Rotate every page clockwise by the given angle in degrees", + + EffortMethod: "Method", + EffortSpeed: "Speed", + EffortEffort: "Effort", + TipEffortWebp: "WEBP method, higher is better/slower (0-6, default 4)", + TipEffortAvif: "AVIF speed, higher is faster/worse (0-10, default 10)", + TipEffortJxl: "JXL effort, higher is better/slower (1-10, default 7)", + + BtnAddFiles: "Add &Files...", + BtnAddDir: "Add &Dir...", + BtnRemove: "Remove", + BtnRemoveAll: "Remove All", + BtnThumbnail: "Thumbnail", + BtnCover: "Cover", + BtnConvert: "&Convert", + BtnCancel: "Cancel", + TipCancel: "Cancel the running operation (or press Esc)", + BtnReset: "Reset", + TipReset: "Restore all settings to their defaults", + BtnSave: "Save", + TipSave: "Save current settings to a profile", + BtnCommand: "Command", + TipCommand: "Show the equivalent command line", + LblProfile: "Profile:", + TipProfile: "Select a settings profile", + + TipThumbnail: "Extract cover thumbnails", + TipCover: "Extract covers", + TipConvert: "Convert files to the selected format", + + StatusNeedFilesAndDir: "Add files and set output directory", + StatusNeedFiles: "Add files", + StatusNeedOutDir: "Set output directory", + StatusFileOf: "File %d of %d", + + FilterNearest: "NearestNeighbor is the fastest resampling filter, no antialiasing", + FilterBox: "Box filter (averaging pixels)", + FilterLinear: "Linear is the bilinear filter, smooth and reasonably fast", + FilterMitchell: "MitchellNetravali is a smooth bicubic filter", + FilterCatmull: "CatmullRom is a sharp bicubic filter", + FilterGaussian: "Gaussian is a blurring filter that uses gaussian function, useful for noise removal", + FilterLanczos: "Lanczos is a high-quality resampling filter, it's slower than cubic filters", + + DlgAddFiles: "Add Files", + DlgAddDir: "Add Directory", + DlgOutputDir: "Output Directory", + DlgOutputFile: "Output File", + DlgCommandLine: "Command Line", + DlgSaveProfile: "Save Profile", + + ParamName: "Name: %s\n", + MsgInvalidNameTitle: "Invalid Name", + MsgInvalidNameBody: "Profile name must not be empty or contain '.' or ';'.", + + NoPreview: "No preview", + }) +} diff --git a/cmd/cbconvert-gui/i18n/i18n_es.go b/cmd/cbconvert-gui/i18n/i18n_es.go new file mode 100644 index 0000000..e78dba1 --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n_es.go @@ -0,0 +1,128 @@ +package i18n + +func init() { + register("SPANISH", map[string]string{ + ColTitle: "Título", + ColType: "Tipo", + ColSize: "Tamaño (MiB)", + + TabInput: "Entrada", + TabOutput: "Salida", + TabImage: "Imagen", + TabTransform: "Transformar", + + LblPage: "Página:", + TipPage: "Previsualizar otra página del cómic seleccionado", + + TglRecursive: " Recorrer subdirectorios", + TipRecursive: "Procesar subdirectorios de forma recursiva", + TglNoRGB: " Solo imágenes en escala de grises", + TipNoRGB: "No convertir imágenes que tengan espacio de color RGB", + TglNoCover: " Excluir la portada", + TipNoCover: "No convertir la imagen de portada", + TglNoNonImage: " Eliminar archivos que no sean imágenes del archivo", + TipNoNonImage: "Eliminar archivos .nfo, .xml, .txt del archivo", + TglNoConvert: " No transformar ni convertir imágenes", + TipNoConvert: "Copiar imágenes del archivo o directorio sin modificaciones", + LblMinSize: "Tamaño mínimo (MiB):", + TipSize: "Procesar solo archivos mayores que el tamaño mínimo", + LblDPI: "DPI del documento:", + TipDPI: "Resolución para renderizar documentos (PDF, EPUB, etc.); el valor predeterminado es 300", + + LblOutDir: "Directorio de salida:", + TipOutDir: "Directorio donde se escriben los archivos convertidos (obligatorio)", + BtnBrowse: "Examinar...", + LblSuffix: "Añadir sufijo al archivo de salida:", + TipSuffix: "Añadir sufijo al nombre de archivo, p. ej. nombrearchivo_sufijo.cbz", + LblArchive: "Formato de archivo:", + TipArchive: "Contenedor de salida: ZIP (.cbz) o TAR sin comprimir (.cbt)", + LblCompression: "Compresión:", + TipZipLevel: "Compresión ZIP: Almacenar la desactiva, 1 es la más rápida, 9 la más pequeña", + TglCombine: " Combinar en un solo archivo", + TipCombine: "Fusionar todos los archivos listados en un solo archivo", + LblOutFile: "Archivo de salida:", + TipOutFile: "Nombre del archivo combinado (predeterminado: primera entrada + -combined)", + + LblFormat: "Formato:", + TipFormat: "Formato de imagen de salida para las páginas convertidas", + LblSize: "Tamaño:", + CueWidth: "ancho", + CueHeight: "alto", + TipWidthHeight: "Si no se define el ancho o el alto, se conserva la relación de aspecto de la imagen", + TglFit: " Ajuste óptimo", + TipFit: "Ajuste óptimo al ancho y alto requeridos", + TglNoUpscale: " No ampliar", + TipNoUpscale: "No ampliar imágenes que ya son más pequeñas que el tamaño solicitado", + LblFilter: "Filtro de redimensionado:", + LblQuality: "Calidad: ", + TipQuality: "La calidad afecta a JPEG, WEBP, AVIF y JXL", + LblEffort: "Esfuerzo:", + TipEffort: "Velocidad/esfuerzo del codificador (WEBP, AVIF, JXL)", + TglLossless: " Sin pérdidas", + TipLossless: "Compresión sin pérdidas (WEBP, AVIF, JXL), ignora la calidad", + TglGrayscale: " Escala de grises", + TipGrayscale: "Convertir imágenes a escala de grises (monocromático)", + + LblBrightness: "Brillo: ", + TipBrightness: "Ajustar el brillo de las imágenes", + LblContrast: "Contraste: ", + TipContrast: "Ajustar el contraste de las imágenes", + LblRotate: "Rotar:", + TipRotate: "Rotar cada página en sentido horario el ángulo dado en grados", + + EffortMethod: "Método", + EffortSpeed: "Velocidad", + EffortEffort: "Esfuerzo", + TipEffortWebp: "Método WEBP, más alto es mejor/más lento (0-6, predeterminado 4)", + TipEffortAvif: "Velocidad AVIF, más alto es más rápido/peor (0-10, predeterminado 10)", + TipEffortJxl: "Esfuerzo JXL, más alto es mejor/más lento (1-10, predeterminado 7)", + + BtnAddFiles: "Añadir &archivos...", + BtnAddDir: "Añadir &directorio...", + BtnRemove: "Eliminar", + BtnRemoveAll: "Eliminar todo", + BtnThumbnail: "Miniatura", + BtnCover: "Portada", + BtnConvert: "&Convertir", + BtnCancel: "Cancelar", + TipCancel: "Cancelar la operación en curso (o pulsar Esc)", + BtnReset: "Restablecer", + TipReset: "Restaurar todos los ajustes a sus valores predeterminados", + BtnSave: "Guardar", + TipSave: "Guardar los ajustes actuales en un perfil", + BtnCommand: "Comando", + TipCommand: "Mostrar la línea de comandos equivalente", + LblProfile: "Perfil:", + TipProfile: "Seleccionar un perfil de ajustes", + + TipThumbnail: "Extraer miniaturas de portada", + TipCover: "Extraer portadas", + TipConvert: "Convertir archivos al formato seleccionado", + + StatusNeedFilesAndDir: "Añadir archivos y establecer el directorio de salida", + StatusNeedFiles: "Añadir archivos", + StatusNeedOutDir: "Establecer el directorio de salida", + StatusFileOf: "Archivo %d de %d", + + FilterNearest: "NearestNeighbor es el filtro de remuestreo más rápido, sin antialiasing", + FilterBox: "Filtro Box (promedio de píxeles)", + FilterLinear: "Linear es el filtro bilineal, suave y razonablemente rápido", + FilterMitchell: "MitchellNetravali es un filtro bicúbico suave", + FilterCatmull: "CatmullRom es un filtro bicúbico nítido", + FilterGaussian: "Gaussian es un filtro de desenfoque que usa la función gaussiana, útil para eliminar ruido", + FilterLanczos: "Lanczos es un filtro de remuestreo de alta calidad, más lento que los filtros cúbicos", + + DlgAddFiles: "Añadir archivos", + DlgAddDir: "Añadir directorio", + DlgOutputDir: "Directorio de salida", + DlgOutputFile: "Archivo de salida", + DlgCommandLine: "Línea de comandos", + DlgSaveProfile: "Guardar perfil", + + ParamName: "Nombre: %s\n", + MsgInvalidNameTitle: "Nombre no válido", + MsgInvalidNameBody: "El nombre del perfil no debe estar vacío ni contener '.' o ';'.", + + NoPreview: "Sin vista previa", + }) +} diff --git a/cmd/cbconvert-gui/i18n/i18n_fr.go b/cmd/cbconvert-gui/i18n/i18n_fr.go new file mode 100644 index 0000000..b03f574 --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n_fr.go @@ -0,0 +1,128 @@ +package i18n + +func init() { + register("FRENCH", map[string]string{ + ColTitle: "Titre", + ColType: "Type", + ColSize: "Taille (Mio)", + + TabInput: "Entrée", + TabOutput: "Sortie", + TabImage: "Image", + TabTransform: "Transformation", + + LblPage: "Page :", + TipPage: "Prévisualiser une autre page de la bande dessinée sélectionnée", + + TglRecursive: " Parcourir les sous-dossiers", + TipRecursive: "Traiter les sous-dossiers de manière récursive", + TglNoRGB: " Images en niveaux de gris uniquement", + TipNoRGB: "Ne pas convertir les images ayant un espace colorimétrique RVB", + TglNoCover: " Exclure la couverture", + TipNoCover: "Ne pas convertir l'image de couverture", + TglNoNonImage: " Supprimer les fichiers non-image de l'archive", + TipNoNonImage: "Supprimer les fichiers .nfo, .xml, .txt de l'archive", + TglNoConvert: " Ne pas transformer ni convertir les images", + TipNoConvert: "Copier les images de l'archive ou du dossier sans modifications", + LblMinSize: "Taille minimale (Mio) :", + TipSize: "Ne traiter que les fichiers plus grands que la taille minimale", + LblDPI: "DPI du document :", + TipDPI: "Résolution pour le rendu des documents (PDF, EPUB, etc.) ; la valeur par défaut est 300", + + LblOutDir: "Dossier de sortie :", + TipOutDir: "Dossier où les fichiers convertis sont écrits (obligatoire)", + BtnBrowse: "Parcourir...", + LblSuffix: "Ajouter un suffixe au fichier de sortie :", + TipSuffix: "Ajouter un suffixe au nom de fichier, par ex. nomfichier_suffixe.cbz", + LblArchive: "Format d'archive :", + TipArchive: "Conteneur de sortie : ZIP (.cbz) ou TAR non compressé (.cbt)", + LblCompression: "Compression :", + TipZipLevel: "Compression ZIP : Stocker la désactive, 1 est le plus rapide, 9 le plus petit", + TglCombine: " Combiner en un seul fichier", + TipCombine: "Fusionner tous les fichiers listés en une seule archive", + LblOutFile: "Fichier de sortie :", + TipOutFile: "Nom du fichier combiné (par défaut : première entrée + -combined)", + + LblFormat: "Format :", + TipFormat: "Format d'image de sortie pour les pages converties", + LblSize: "Taille :", + CueWidth: "largeur", + CueHeight: "hauteur", + TipWidthHeight: "Si la largeur ou la hauteur n'est pas définie, le rapport d'aspect de l'image est conservé", + TglFit: " Ajustement optimal", + TipFit: "Ajustement optimal à la largeur et la hauteur requises", + TglNoUpscale: " Ne pas agrandir", + TipNoUpscale: "Ne pas agrandir les images déjà plus petites que la taille demandée", + LblFilter: "Filtre de redimensionnement :", + LblQuality: "Qualité : ", + TipQuality: "La qualité concerne JPEG, WEBP, AVIF et JXL", + LblEffort: "Effort :", + TipEffort: "Vitesse/effort de l'encodeur (WEBP, AVIF, JXL)", + TglLossless: " Sans perte", + TipLossless: "Compression sans perte (WEBP, AVIF, JXL), ignore la qualité", + TglGrayscale: " Niveaux de gris", + TipGrayscale: "Convertir les images en niveaux de gris (monochrome)", + + LblBrightness: "Luminosité : ", + TipBrightness: "Ajuster la luminosité des images", + LblContrast: "Contraste : ", + TipContrast: "Ajuster le contraste des images", + LblRotate: "Rotation :", + TipRotate: "Faire pivoter chaque page dans le sens horaire de l'angle donné en degrés", + + EffortMethod: "Méthode", + EffortSpeed: "Vitesse", + EffortEffort: "Effort", + TipEffortWebp: "Méthode WEBP, plus élevé est meilleur/plus lent (0-6, défaut 4)", + TipEffortAvif: "Vitesse AVIF, plus élevé est plus rapide/moins bon (0-10, défaut 10)", + TipEffortJxl: "Effort JXL, plus élevé est meilleur/plus lent (1-10, défaut 7)", + + BtnAddFiles: "Ajouter des &fichiers...", + BtnAddDir: "Ajouter un &dossier...", + BtnRemove: "Supprimer", + BtnRemoveAll: "Tout supprimer", + BtnThumbnail: "Miniature", + BtnCover: "Couverture", + BtnConvert: "&Convertir", + BtnCancel: "Annuler", + TipCancel: "Annuler l'opération en cours (ou appuyer sur Échap)", + BtnReset: "Réinitialiser", + TipReset: "Restaurer tous les paramètres à leurs valeurs par défaut", + BtnSave: "Enregistrer", + TipSave: "Enregistrer les paramètres actuels dans un profil", + BtnCommand: "Commande", + TipCommand: "Afficher la ligne de commande équivalente", + LblProfile: "Profil :", + TipProfile: "Sélectionner un profil de paramètres", + + TipThumbnail: "Extraire les miniatures de couverture", + TipCover: "Extraire les couvertures", + TipConvert: "Convertir les fichiers vers le format sélectionné", + + StatusNeedFilesAndDir: "Ajouter des fichiers et définir le dossier de sortie", + StatusNeedFiles: "Ajouter des fichiers", + StatusNeedOutDir: "Définir le dossier de sortie", + StatusFileOf: "Fichier %d sur %d", + + FilterNearest: "NearestNeighbor est le filtre de rééchantillonnage le plus rapide, sans anticrénelage", + FilterBox: "Filtre Box (moyenne des pixels)", + FilterLinear: "Linear est le filtre bilinéaire, lisse et raisonnablement rapide", + FilterMitchell: "MitchellNetravali est un filtre bicubique lisse", + FilterCatmull: "CatmullRom est un filtre bicubique net", + FilterGaussian: "Gaussian est un filtre de flou utilisant la fonction gaussienne, utile pour la réduction du bruit", + FilterLanczos: "Lanczos est un filtre de rééchantillonnage de haute qualité, plus lent que les filtres cubiques", + + DlgAddFiles: "Ajouter des fichiers", + DlgAddDir: "Ajouter un dossier", + DlgOutputDir: "Dossier de sortie", + DlgOutputFile: "Fichier de sortie", + DlgCommandLine: "Ligne de commande", + DlgSaveProfile: "Enregistrer le profil", + + ParamName: "Nom : %s\n", + MsgInvalidNameTitle: "Nom invalide", + MsgInvalidNameBody: "Le nom du profil ne doit pas être vide ni contenir '.' ou ';'.", + + NoPreview: "Aucun aperçu", + }) +} diff --git a/cmd/cbconvert-gui/i18n/i18n_it.go b/cmd/cbconvert-gui/i18n/i18n_it.go new file mode 100644 index 0000000..b041d4c --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n_it.go @@ -0,0 +1,128 @@ +package i18n + +func init() { + register("ITALIAN", map[string]string{ + ColTitle: "Titolo", + ColType: "Tipo", + ColSize: "Dimensione (MiB)", + + TabInput: "Ingresso", + TabOutput: "Uscita", + TabImage: "Immagine", + TabTransform: "Trasforma", + + LblPage: "Pagina:", + TipPage: "Anteprima di un'altra pagina del fumetto selezionato", + + TglRecursive: " Esplora sottocartelle", + TipRecursive: "Elabora le sottocartelle in modo ricorsivo", + TglNoRGB: " Solo immagini in scala di grigi", + TipNoRGB: "Non convertire le immagini con spazio colore RGB", + TglNoCover: " Escludi la copertina", + TipNoCover: "Non convertire l'immagine di copertina", + TglNoNonImage: " Rimuovi i file non immagine dall'archivio", + TipNoNonImage: "Rimuovi i file .nfo, .xml, .txt dall'archivio", + TglNoConvert: " Non trasformare né convertire le immagini", + TipNoConvert: "Copia le immagini dall'archivio o dalla cartella senza modifiche", + LblMinSize: "Dimensione minima (MiB):", + TipSize: "Elabora solo i file più grandi della dimensione minima", + LblDPI: "DPI del documento:", + TipDPI: "Risoluzione per il rendering dei documenti (PDF, EPUB, ecc.); il valore predefinito è 300", + + LblOutDir: "Cartella di uscita:", + TipOutDir: "Cartella in cui vengono scritti i file convertiti (obbligatoria)", + BtnBrowse: "Sfoglia...", + LblSuffix: "Aggiungi suffisso al file di uscita:", + TipSuffix: "Aggiungi un suffisso al nome del file, ad es. nomefile_suffisso.cbz", + LblArchive: "Formato archivio:", + TipArchive: "Contenitore di uscita: ZIP (.cbz) o TAR non compresso (.cbt)", + LblCompression: "Compressione:", + TipZipLevel: "Compressione ZIP: Memorizza la disattiva, 1 è la più veloce, 9 la più piccola", + TglCombine: " Combina in un unico file", + TipCombine: "Unisci tutti i file elencati in un unico archivio", + LblOutFile: "File di uscita:", + TipOutFile: "Nome del file combinato (predefinito: primo ingresso + -combined)", + + LblFormat: "Formato:", + TipFormat: "Formato immagine di uscita per le pagine convertite", + LblSize: "Dimensione:", + CueWidth: "larghezza", + CueHeight: "altezza", + TipWidthHeight: "Se la larghezza o l'altezza non è impostata, viene mantenuto il rapporto d'aspetto dell'immagine", + TglFit: " Adattamento ottimale", + TipFit: "Adattamento ottimale alla larghezza e all'altezza richieste", + TglNoUpscale: " Non ingrandire", + TipNoUpscale: "Non ingrandire le immagini già più piccole della dimensione richiesta", + LblFilter: "Filtro di ridimensionamento:", + LblQuality: "Qualità: ", + TipQuality: "La qualità riguarda JPEG, WEBP, AVIF e JXL", + LblEffort: "Sforzo:", + TipEffort: "Velocità/sforzo del codificatore (WEBP, AVIF, JXL)", + TglLossless: " Senza perdita", + TipLossless: "Compressione senza perdita (WEBP, AVIF, JXL), ignora la qualità", + TglGrayscale: " Scala di grigi", + TipGrayscale: "Converti le immagini in scala di grigi (monocromatico)", + + LblBrightness: "Luminosità: ", + TipBrightness: "Regola la luminosità delle immagini", + LblContrast: "Contrasto: ", + TipContrast: "Regola il contrasto delle immagini", + LblRotate: "Ruota:", + TipRotate: "Ruota ogni pagina in senso orario dell'angolo indicato in gradi", + + EffortMethod: "Metodo", + EffortSpeed: "Velocità", + EffortEffort: "Sforzo", + TipEffortWebp: "Metodo WEBP, più alto è migliore/più lento (0-6, predefinito 4)", + TipEffortAvif: "Velocità AVIF, più alto è più veloce/peggiore (0-10, predefinito 10)", + TipEffortJxl: "Sforzo JXL, più alto è migliore/più lento (1-10, predefinito 7)", + + BtnAddFiles: "Aggiungi &file...", + BtnAddDir: "Aggiungi &cartella...", + BtnRemove: "Rimuovi", + BtnRemoveAll: "Rimuovi tutto", + BtnThumbnail: "Miniatura", + BtnCover: "Copertina", + BtnConvert: "&Converti", + BtnCancel: "Annulla", + TipCancel: "Annulla l'operazione in corso (o premi Esc)", + BtnReset: "Ripristina", + TipReset: "Ripristina tutte le impostazioni ai valori predefiniti", + BtnSave: "Salva", + TipSave: "Salva le impostazioni correnti in un profilo", + BtnCommand: "Comando", + TipCommand: "Mostra la riga di comando equivalente", + LblProfile: "Profilo:", + TipProfile: "Seleziona un profilo di impostazioni", + + TipThumbnail: "Estrai le miniature delle copertine", + TipCover: "Estrai le copertine", + TipConvert: "Converti i file nel formato selezionato", + + StatusNeedFilesAndDir: "Aggiungi file e imposta la cartella di uscita", + StatusNeedFiles: "Aggiungi file", + StatusNeedOutDir: "Imposta la cartella di uscita", + StatusFileOf: "File %d di %d", + + FilterNearest: "NearestNeighbor è il filtro di ricampionamento più veloce, senza antialiasing", + FilterBox: "Filtro Box (media dei pixel)", + FilterLinear: "Linear è il filtro bilineare, morbido e ragionevolmente veloce", + FilterMitchell: "MitchellNetravali è un filtro bicubico morbido", + FilterCatmull: "CatmullRom è un filtro bicubico nitido", + FilterGaussian: "Gaussian è un filtro di sfocatura che usa la funzione gaussiana, utile per la rimozione del rumore", + FilterLanczos: "Lanczos è un filtro di ricampionamento di alta qualità, più lento dei filtri cubici", + + DlgAddFiles: "Aggiungi file", + DlgAddDir: "Aggiungi cartella", + DlgOutputDir: "Cartella di uscita", + DlgOutputFile: "File di uscita", + DlgCommandLine: "Riga di comando", + DlgSaveProfile: "Salva profilo", + + ParamName: "Nome: %s\n", + MsgInvalidNameTitle: "Nome non valido", + MsgInvalidNameBody: "Il nome del profilo non deve essere vuoto né contenere '.' o ';'.", + + NoPreview: "Nessuna anteprima", + }) +} diff --git a/cmd/cbconvert-gui/i18n/i18n_ja.go b/cmd/cbconvert-gui/i18n/i18n_ja.go new file mode 100644 index 0000000..1cc5530 --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n_ja.go @@ -0,0 +1,128 @@ +package i18n + +func init() { + register("JAPANESE", map[string]string{ + ColTitle: "タイトル", + ColType: "種類", + ColSize: "サイズ (MiB)", + + TabInput: "入力", + TabOutput: "出力", + TabImage: "画像", + TabTransform: "変換", + + LblPage: "ページ:", + TipPage: "選択したコミックの別のページをプレビュー", + + TglRecursive: " サブディレクトリを再帰的に処理", + TipRecursive: "サブディレクトリを再帰的に処理する", + TglNoRGB: " グレースケール画像のみ", + TipNoRGB: "RGB 色空間の画像を変換しない", + TglNoCover: " 表紙を除外", + TipNoCover: "表紙画像を変換しない", + TglNoNonImage: " アーカイブから画像以外のファイルを削除", + TipNoNonImage: "アーカイブから .nfo、.xml、.txt ファイルを削除する", + TglNoConvert: " 画像を変換・変形しない", + TipNoConvert: "アーカイブまたはディレクトリから画像を変更せずにコピーする", + LblMinSize: "最小サイズ (MiB):", + TipSize: "最小サイズより大きいファイルのみ処理する", + LblDPI: "ドキュメント DPI:", + TipDPI: "ドキュメント(PDF、EPUB など)をレンダリングする解像度。既定値は 300", + + LblOutDir: "出力ディレクトリ:", + TipOutDir: "変換されたファイルが書き込まれるディレクトリ(必須)", + BtnBrowse: "参照...", + LblSuffix: "出力ファイルにサフィックスを追加:", + TipSuffix: "ファイル名にサフィックスを追加する。例: filename_suffix.cbz", + LblArchive: "アーカイブ形式:", + TipArchive: "出力コンテナ: ZIP (.cbz) または非圧縮の TAR (.cbt)", + LblCompression: "圧縮:", + TipZipLevel: "ZIP 圧縮: 「保存」で無効化、1 が最速、9 が最小", + TglCombine: " 単一ファイルに結合", + TipCombine: "リストされたすべてのファイルを 1 つのアーカイブに結合する", + LblOutFile: "出力ファイル:", + TipOutFile: "結合ファイル名(既定: 最初の入力 + -combined)", + + LblFormat: "形式:", + TipFormat: "変換されるページの出力画像形式", + LblSize: "サイズ:", + CueWidth: "幅", + CueHeight: "高さ", + TipWidthHeight: "幅または高さが設定されていない場合、画像の縦横比が保持されます", + TglFit: " 最適化", + TipFit: "必要な幅と高さに最適化", + TglNoUpscale: " 拡大しない", + TipNoUpscale: "要求されたサイズより既に小さい画像を拡大しない", + LblFilter: "リサイズフィルター:", + LblQuality: "品質:", + TipQuality: "品質は JPEG、WEBP、AVIF、JXL に影響します", + LblEffort: "労力:", + TipEffort: "エンコーダーの速度/労力(WEBP、AVIF、JXL)", + TglLossless: " ロスレス", + TipLossless: "ロスレス圧縮(WEBP、AVIF、JXL)、品質を無視します", + TglGrayscale: " グレースケール", + TipGrayscale: "画像をグレースケール(モノクロ)に変換する", + + LblBrightness: "明るさ:", + TipBrightness: "画像の明るさを調整する", + LblContrast: "コントラスト:", + TipContrast: "画像のコントラストを調整する", + LblRotate: "回転:", + TipRotate: "各ページを指定した角度(度)だけ時計回りに回転する", + + EffortMethod: "方式", + EffortSpeed: "速度", + EffortEffort: "労力", + TipEffortWebp: "WEBP 方式、高いほど高品質/低速(0-6、既定 4)", + TipEffortAvif: "AVIF 速度、高いほど高速/低品質(0-10、既定 10)", + TipEffortJxl: "JXL 労力、高いほど高品質/低速(1-10、既定 7)", + + BtnAddFiles: "ファイルを追加(&F)...", + BtnAddDir: "ディレクトリを追加(&D)...", + BtnRemove: "削除", + BtnRemoveAll: "すべて削除", + BtnThumbnail: "サムネイル", + BtnCover: "表紙", + BtnConvert: "変換(&C)", + BtnCancel: "キャンセル", + TipCancel: "実行中の操作をキャンセル(または Esc キーを押す)", + BtnReset: "リセット", + TipReset: "すべての設定を既定値に戻す", + BtnSave: "保存", + TipSave: "現在の設定をプロファイルに保存する", + BtnCommand: "コマンド", + TipCommand: "同等のコマンドラインを表示する", + LblProfile: "プロファイル:", + TipProfile: "設定プロファイルを選択する", + + TipThumbnail: "表紙のサムネイルを抽出する", + TipCover: "表紙を抽出する", + TipConvert: "ファイルを選択した形式に変換する", + + StatusNeedFilesAndDir: "ファイルを追加し、出力ディレクトリを設定してください", + StatusNeedFiles: "ファイルを追加してください", + StatusNeedOutDir: "出力ディレクトリを設定してください", + StatusFileOf: "ファイル %d / %d", + + FilterNearest: "NearestNeighbor は最速のリサンプリングフィルターで、アンチエイリアスなし", + FilterBox: "Box フィルター(ピクセルの平均化)", + FilterLinear: "Linear はバイリニアフィルターで、滑らかでそれなりに高速", + FilterMitchell: "MitchellNetravali は滑らかなバイキュービックフィルター", + FilterCatmull: "CatmullRom はシャープなバイキュービックフィルター", + FilterGaussian: "Gaussian はガウス関数を使用するぼかしフィルターで、ノイズ除去に便利", + FilterLanczos: "Lanczos は高品質なリサンプリングフィルターで、キュービックフィルターより低速", + + DlgAddFiles: "ファイルを追加", + DlgAddDir: "ディレクトリを追加", + DlgOutputDir: "出力ディレクトリ", + DlgOutputFile: "出力ファイル", + DlgCommandLine: "コマンドライン", + DlgSaveProfile: "プロファイルを保存", + + ParamName: "名前:%s\n", + MsgInvalidNameTitle: "無効な名前", + MsgInvalidNameBody: "プロファイル名は空にすることはできず、'.' または ';' を含めることはできません。", + + NoPreview: "プレビューなし", + }) +} diff --git a/cmd/cbconvert-gui/i18n/i18n_pt.go b/cmd/cbconvert-gui/i18n/i18n_pt.go new file mode 100644 index 0000000..a060ac7 --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n_pt.go @@ -0,0 +1,128 @@ +package i18n + +func init() { + register("PORTUGUESE", map[string]string{ + ColTitle: "Título", + ColType: "Tipo", + ColSize: "Tamanho (MiB)", + + TabInput: "Entrada", + TabOutput: "Saída", + TabImage: "Imagem", + TabTransform: "Transformar", + + LblPage: "Página:", + TipPage: "Pré-visualizar outra página da revista em quadrinhos selecionada", + + TglRecursive: " Percorrer subdiretórios", + TipRecursive: "Processar subdiretórios recursivamente", + TglNoRGB: " Apenas imagens em escala de cinza", + TipNoRGB: "Não converter imagens que tenham espaço de cor RGB", + TglNoCover: " Excluir a capa", + TipNoCover: "Não converter a imagem de capa", + TglNoNonImage: " Remover arquivos não-imagem do arquivo", + TipNoNonImage: "Remover arquivos .nfo, .xml, .txt do arquivo", + TglNoConvert: " Não transformar nem converter imagens", + TipNoConvert: "Copiar imagens do arquivo ou diretório sem modificações", + LblMinSize: "Tamanho mínimo (MiB):", + TipSize: "Processar apenas arquivos maiores que o tamanho mínimo", + LblDPI: "DPI do documento:", + TipDPI: "Resolução para renderizar documentos (PDF, EPUB, etc.); o padrão é 300", + + LblOutDir: "Diretório de saída:", + TipOutDir: "Diretório onde os arquivos convertidos são gravados (obrigatório)", + BtnBrowse: "Procurar...", + LblSuffix: "Adicionar sufixo ao arquivo de saída:", + TipSuffix: "Adicionar sufixo ao nome do arquivo, p. ex. nomearquivo_sufixo.cbz", + LblArchive: "Formato de arquivo:", + TipArchive: "Contêiner de saída: ZIP (.cbz) ou TAR não comprimido (.cbt)", + LblCompression: "Compressão:", + TipZipLevel: "Compressão ZIP: Armazenar a desativa, 1 é a mais rápida, 9 a menor", + TglCombine: " Combinar em um único arquivo", + TipCombine: "Mesclar todos os arquivos listados em um único arquivo", + LblOutFile: "Arquivo de saída:", + TipOutFile: "Nome do arquivo combinado (padrão: primeira entrada + -combined)", + + LblFormat: "Formato:", + TipFormat: "Formato de imagem de saída para as páginas convertidas", + LblSize: "Tamanho:", + CueWidth: "largura", + CueHeight: "altura", + TipWidthHeight: "Se a largura ou a altura não for definida, a proporção da imagem é preservada", + TglFit: " Melhor ajuste", + TipFit: "Melhor ajuste à largura e altura desejadas", + TglNoUpscale: " Não ampliar", + TipNoUpscale: "Não ampliar imagens que já são menores que o tamanho solicitado", + LblFilter: "Filtro de redimensionamento:", + LblQuality: "Qualidade: ", + TipQuality: "A qualidade afeta JPEG, WEBP, AVIF e JXL", + LblEffort: "Esforço:", + TipEffort: "Velocidade/esforço do codificador (WEBP, AVIF, JXL)", + TglLossless: " Sem perdas", + TipLossless: "Compressão sem perdas (WEBP, AVIF, JXL), ignora a qualidade", + TglGrayscale: " Escala de cinza", + TipGrayscale: "Converter imagens para escala de cinza (monocromático)", + + LblBrightness: "Brilho: ", + TipBrightness: "Ajustar o brilho das imagens", + LblContrast: "Contraste: ", + TipContrast: "Ajustar o contraste das imagens", + LblRotate: "Girar:", + TipRotate: "Girar cada página no sentido horário pelo ângulo dado em graus", + + EffortMethod: "Método", + EffortSpeed: "Velocidade", + EffortEffort: "Esforço", + TipEffortWebp: "Método WEBP, mais alto é melhor/mais lento (0-6, padrão 4)", + TipEffortAvif: "Velocidade AVIF, mais alto é mais rápido/pior (0-10, padrão 10)", + TipEffortJxl: "Esforço JXL, mais alto é melhor/mais lento (1-10, padrão 7)", + + BtnAddFiles: "Adicionar &arquivos...", + BtnAddDir: "Adicionar &diretório...", + BtnRemove: "Remover", + BtnRemoveAll: "Remover tudo", + BtnThumbnail: "Miniatura", + BtnCover: "Capa", + BtnConvert: "&Converter", + BtnCancel: "Cancelar", + TipCancel: "Cancelar a operação em andamento (ou pressionar Esc)", + BtnReset: "Redefinir", + TipReset: "Restaurar todas as configurações para os valores padrão", + BtnSave: "Salvar", + TipSave: "Salvar as configurações atuais em um perfil", + BtnCommand: "Comando", + TipCommand: "Mostrar a linha de comando equivalente", + LblProfile: "Perfil:", + TipProfile: "Selecionar um perfil de configurações", + + TipThumbnail: "Extrair miniaturas de capa", + TipCover: "Extrair capas", + TipConvert: "Converter arquivos para o formato selecionado", + + StatusNeedFilesAndDir: "Adicionar arquivos e definir o diretório de saída", + StatusNeedFiles: "Adicionar arquivos", + StatusNeedOutDir: "Definir o diretório de saída", + StatusFileOf: "Arquivo %d de %d", + + FilterNearest: "NearestNeighbor é o filtro de reamostragem mais rápido, sem antisserrilhamento", + FilterBox: "Filtro Box (média dos pixels)", + FilterLinear: "Linear é o filtro bilinear, suave e razoavelmente rápido", + FilterMitchell: "MitchellNetravali é um filtro bicúbico suave", + FilterCatmull: "CatmullRom é um filtro bicúbico nítido", + FilterGaussian: "Gaussian é um filtro de desfoque que usa a função gaussiana, útil para remoção de ruído", + FilterLanczos: "Lanczos é um filtro de reamostragem de alta qualidade, mais lento que os filtros cúbicos", + + DlgAddFiles: "Adicionar arquivos", + DlgAddDir: "Adicionar diretório", + DlgOutputDir: "Diretório de saída", + DlgOutputFile: "Arquivo de saída", + DlgCommandLine: "Linha de comando", + DlgSaveProfile: "Salvar perfil", + + ParamName: "Nome: %s\n", + MsgInvalidNameTitle: "Nome inválido", + MsgInvalidNameBody: "O nome do perfil não deve estar vazio nem conter '.' ou ';'.", + + NoPreview: "Sem pré-visualização", + }) +} diff --git a/cmd/cbconvert-gui/i18n/i18n_ru.go b/cmd/cbconvert-gui/i18n/i18n_ru.go new file mode 100644 index 0000000..aa2447d --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n_ru.go @@ -0,0 +1,128 @@ +package i18n + +func init() { + register("RUSSIAN", map[string]string{ + ColTitle: "Название", + ColType: "Тип", + ColSize: "Размер (МиБ)", + + TabInput: "Ввод", + TabOutput: "Вывод", + TabImage: "Изображение", + TabTransform: "Преобразование", + + LblPage: "Страница:", + TipPage: "Предпросмотр другой страницы выбранного комикса", + + TglRecursive: " Обрабатывать подкаталоги", + TipRecursive: "Рекурсивно обрабатывать подкаталоги", + TglNoRGB: " Только изображения в оттенках серого", + TipNoRGB: "Не преобразовывать изображения в цветовом пространстве RGB", + TglNoCover: " Исключить обложку", + TipNoCover: "Не преобразовывать изображение обложки", + TglNoNonImage: " Удалить из архива файлы, не являющиеся изображениями", + TipNoNonImage: "Удалить из архива файлы .nfo, .xml, .txt", + TglNoConvert: " Не преобразовывать изображения", + TipNoConvert: "Копировать изображения из архива или каталога без изменений", + LblMinSize: "Минимальный размер (МиБ):", + TipSize: "Обрабатывать только файлы больше минимального размера", + LblDPI: "DPI документа:", + TipDPI: "Разрешение для рендеринга документов (PDF, EPUB и т. д.); по умолчанию 300", + + LblOutDir: "Каталог вывода:", + TipOutDir: "Каталог, в который записываются преобразованные файлы (обязательно)", + BtnBrowse: "Обзор...", + LblSuffix: "Добавить суффикс к выходному файлу:", + TipSuffix: "Добавить суффикс к имени файла, например имяфайла_суффикс.cbz", + LblArchive: "Формат архива:", + TipArchive: "Выходной контейнер: ZIP (.cbz) или несжатый TAR (.cbt)", + LblCompression: "Сжатие:", + TipZipLevel: "Сжатие ZIP: «Хранить» отключает его, 1 — самое быстрое, 9 — наименьшее", + TglCombine: " Объединить в один файл", + TipCombine: "Объединить все перечисленные файлы в один архив", + LblOutFile: "Выходной файл:", + TipOutFile: "Имя объединённого файла (по умолчанию: первый ввод + -combined)", + + LblFormat: "Формат:", + TipFormat: "Выходной формат изображения для преобразованных страниц", + LblSize: "Размер:", + CueWidth: "ширина", + CueHeight: "высота", + TipWidthHeight: "Если ширина или высота не задана, соотношение сторон изображения сохраняется", + TglFit: " Наилучшее соответствие", + TipFit: "Наилучшее соответствие требуемой ширине и высоте", + TglNoUpscale: " Не увеличивать", + TipNoUpscale: "Не увеличивать изображения, которые уже меньше запрошенного размера", + LblFilter: "Фильтр масштабирования:", + LblQuality: "Качество: ", + TipQuality: "Качество влияет на JPEG, WEBP, AVIF и JXL", + LblEffort: "Усилие:", + TipEffort: "Скорость/усилие кодировщика (WEBP, AVIF, JXL)", + TglLossless: " Без потерь", + TipLossless: "Сжатие без потерь (WEBP, AVIF, JXL), игнорирует качество", + TglGrayscale: " Оттенки серого", + TipGrayscale: "Преобразовать изображения в оттенки серого (монохромные)", + + LblBrightness: "Яркость: ", + TipBrightness: "Настроить яркость изображений", + LblContrast: "Контраст: ", + TipContrast: "Настроить контраст изображений", + LblRotate: "Поворот:", + TipRotate: "Поворачивать каждую страницу по часовой стрелке на заданный угол в градусах", + + EffortMethod: "Метод", + EffortSpeed: "Скорость", + EffortEffort: "Усилие", + TipEffortWebp: "Метод WEBP, выше — лучше/медленнее (0-6, по умолчанию 4)", + TipEffortAvif: "Скорость AVIF, выше — быстрее/хуже (0-10, по умолчанию 10)", + TipEffortJxl: "Усилие JXL, выше — лучше/медленнее (1-10, по умолчанию 7)", + + BtnAddFiles: "Добавить &файлы...", + BtnAddDir: "Добавить &каталог...", + BtnRemove: "Удалить", + BtnRemoveAll: "Удалить все", + BtnThumbnail: "Эскиз", + BtnCover: "Обложка", + BtnConvert: "&Преобразовать", + BtnCancel: "Отмена", + TipCancel: "Отменить выполняемую операцию (или нажать Esc)", + BtnReset: "Сбросить", + TipReset: "Восстановить все настройки до значений по умолчанию", + BtnSave: "Сохранить", + TipSave: "Сохранить текущие настройки в профиль", + BtnCommand: "Команда", + TipCommand: "Показать эквивалентную командную строку", + LblProfile: "Профиль:", + TipProfile: "Выбрать профиль настроек", + + TipThumbnail: "Извлечь эскизы обложек", + TipCover: "Извлечь обложки", + TipConvert: "Преобразовать файлы в выбранный формат", + + StatusNeedFilesAndDir: "Добавьте файлы и задайте каталог вывода", + StatusNeedFiles: "Добавьте файлы", + StatusNeedOutDir: "Задайте каталог вывода", + StatusFileOf: "Файл %d из %d", + + FilterNearest: "NearestNeighbor — самый быстрый фильтр передискретизации, без сглаживания", + FilterBox: "Фильтр Box (усреднение пикселей)", + FilterLinear: "Linear — билинейный фильтр, гладкий и достаточно быстрый", + FilterMitchell: "MitchellNetravali — гладкий бикубический фильтр", + FilterCatmull: "CatmullRom — резкий бикубический фильтр", + FilterGaussian: "Gaussian — размывающий фильтр на основе функции Гаусса, полезен для удаления шума", + FilterLanczos: "Lanczos — высококачественный фильтр передискретизации, медленнее кубических фильтров", + + DlgAddFiles: "Добавить файлы", + DlgAddDir: "Добавить каталог", + DlgOutputDir: "Каталог вывода", + DlgOutputFile: "Выходной файл", + DlgCommandLine: "Командная строка", + DlgSaveProfile: "Сохранить профиль", + + ParamName: "Имя: %s\n", + MsgInvalidNameTitle: "Недопустимое имя", + MsgInvalidNameBody: "Имя профиля не должно быть пустым или содержать «.» или «;».", + + NoPreview: "Нет предпросмотра", + }) +} diff --git a/cmd/cbconvert-gui/i18n/i18n_zh.go b/cmd/cbconvert-gui/i18n/i18n_zh.go new file mode 100644 index 0000000..65687ae --- /dev/null +++ b/cmd/cbconvert-gui/i18n/i18n_zh.go @@ -0,0 +1,128 @@ +package i18n + +func init() { + register("CHINESE", map[string]string{ + ColTitle: "标题", + ColType: "类型", + ColSize: "大小 (MiB)", + + TabInput: "输入", + TabOutput: "输出", + TabImage: "图像", + TabTransform: "变换", + + LblPage: "页面:", + TipPage: "预览所选漫画的其他页面", + + TglRecursive: " 递归子目录", + TipRecursive: "递归处理子目录", + TglNoRGB: " 仅灰度图像", + TipNoRGB: "不转换具有 RGB 色彩空间的图像", + TglNoCover: " 排除封面", + TipNoCover: "不转换封面图像", + TglNoNonImage: " 从存档中移除非图像文件", + TipNoNonImage: "从存档中移除 .nfo、.xml、.txt 文件", + TglNoConvert: " 不变换或转换图像", + TipNoConvert: "从存档或目录复制图像而不做修改", + LblMinSize: "最小大小 (MiB):", + TipSize: "仅处理大于最小大小的文件", + LblDPI: "文档 DPI:", + TipDPI: "渲染文档的分辨率(PDF、EPUB 等);默认值为 300", + + LblOutDir: "输出目录:", + TipOutDir: "写入转换后文件的目录(必填)", + BtnBrowse: "浏览...", + LblSuffix: "为输出文件添加后缀:", + TipSuffix: "为文件名添加后缀,例如 filename_suffix.cbz", + LblArchive: "存档格式:", + TipArchive: "输出容器:ZIP (.cbz) 或未压缩的 TAR (.cbt)", + LblCompression: "压缩:", + TipZipLevel: "ZIP 压缩:存储将其禁用,1 最快,9 最小", + TglCombine: " 合并为单个文件", + TipCombine: "将所有列出的文件合并为一个存档", + LblOutFile: "输出文件:", + TipOutFile: "合并文件名(默认:第一个输入 + -combined)", + + LblFormat: "格式:", + TipFormat: "转换页面的输出图像格式", + LblSize: "大小:", + CueWidth: "宽度", + CueHeight: "高度", + TipWidthHeight: "如果未设置宽度或高度,则保留图像的纵横比", + TglFit: " 最佳适应", + TipFit: "最佳适应所需的宽度和高度", + TglNoUpscale: " 不放大", + TipNoUpscale: "不放大已经小于请求大小的图像", + LblFilter: "缩放滤镜:", + LblQuality: "质量:", + TipQuality: "质量影响 JPEG、WEBP、AVIF 和 JXL", + LblEffort: "强度:", + TipEffort: "编码器速度/强度(WEBP、AVIF、JXL)", + TglLossless: " 无损", + TipLossless: "无损压缩(WEBP、AVIF、JXL),忽略质量", + TglGrayscale: " 灰度", + TipGrayscale: "将图像转换为灰度(单色)", + + LblBrightness: "亮度:", + TipBrightness: "调整图像的亮度", + LblContrast: "对比度:", + TipContrast: "调整图像的对比度", + LblRotate: "旋转:", + TipRotate: "按给定角度(度)顺时针旋转每一页", + + EffortMethod: "方法", + EffortSpeed: "速度", + EffortEffort: "强度", + TipEffortWebp: "WEBP 方法,越高越好/越慢(0-6,默认 4)", + TipEffortAvif: "AVIF 速度,越高越快/越差(0-10,默认 10)", + TipEffortJxl: "JXL 强度,越高越好/越慢(1-10,默认 7)", + + BtnAddFiles: "添加文件(&F)...", + BtnAddDir: "添加目录(&D)...", + BtnRemove: "移除", + BtnRemoveAll: "全部移除", + BtnThumbnail: "缩略图", + BtnCover: "封面", + BtnConvert: "转换(&C)", + BtnCancel: "取消", + TipCancel: "取消正在运行的操作(或按 Esc)", + BtnReset: "重置", + TipReset: "将所有设置恢复为默认值", + BtnSave: "保存", + TipSave: "将当前设置保存到配置文件", + BtnCommand: "命令", + TipCommand: "显示等效的命令行", + LblProfile: "配置文件:", + TipProfile: "选择设置配置文件", + + TipThumbnail: "提取封面缩略图", + TipCover: "提取封面", + TipConvert: "将文件转换为所选格式", + + StatusNeedFilesAndDir: "添加文件并设置输出目录", + StatusNeedFiles: "添加文件", + StatusNeedOutDir: "设置输出目录", + StatusFileOf: "文件 %d / %d", + + FilterNearest: "NearestNeighbor 是最快的重采样滤镜,无抗锯齿", + FilterBox: "Box 滤镜(像素平均)", + FilterLinear: "Linear 是双线性滤镜,平滑且相当快", + FilterMitchell: "MitchellNetravali 是平滑的双三次滤镜", + FilterCatmull: "CatmullRom 是锐利的双三次滤镜", + FilterGaussian: "Gaussian 是使用高斯函数的模糊滤镜,适用于降噪", + FilterLanczos: "Lanczos 是高质量的重采样滤镜,比三次滤镜慢", + + DlgAddFiles: "添加文件", + DlgAddDir: "添加目录", + DlgOutputDir: "输出目录", + DlgOutputFile: "输出文件", + DlgCommandLine: "命令行", + DlgSaveProfile: "保存配置文件", + + ParamName: "名称:%s\n", + MsgInvalidNameTitle: "无效名称", + MsgInvalidNameBody: "配置文件名称不能为空,也不能包含 '.' 或 ';'。", + + NoPreview: "无预览", + }) +} diff --git a/cmd/cbconvert-gui/main.go b/cmd/cbconvert-gui/main.go index de346ff..9186195 100644 --- a/cmd/cbconvert-gui/main.go +++ b/cmd/cbconvert-gui/main.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/gen2brain/cbconvert" + "github.com/gen2brain/cbconvert/cmd/cbconvert-gui/i18n" "github.com/gen2brain/iup-go/iup" ) @@ -74,7 +75,11 @@ func main() { iup.SetGlobal("APPNAME", "cbconvert") iup.SetGlobal("APPID", "io.github.gen2brain.cbconvert") + iup.SetGlobal("AUTODARKMODE", "YES") + iup.SetGlobal("GSKRENDERER", "cairo") + + i18n.Init() config = iup.Config() iup.ConfigLoad(config) diff --git a/cmd/cbconvert-gui/options.go b/cmd/cbconvert-gui/options.go index ef3bf68..d7d06a2 100644 --- a/cmd/cbconvert-gui/options.go +++ b/cmd/cbconvert-gui/options.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/gen2brain/cbconvert" + "github.com/gen2brain/cbconvert/cmd/cbconvert-gui/i18n" "github.com/gen2brain/iup-go/iup" ) @@ -70,7 +71,7 @@ func commandLine() string { } func onCommand(iup.Ihandle) int { - iup.GetText("Command Line", commandLine(), -1) + iup.GetText(i18n.Str(i18n.DlgCommandLine), commandLine(), -1) return iup.DEFAULT } diff --git a/cmd/cbconvert-gui/settings.go b/cmd/cbconvert-gui/settings.go index 2505f91..b1e0254 100644 --- a/cmd/cbconvert-gui/settings.go +++ b/cmd/cbconvert-gui/settings.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" + "github.com/gen2brain/cbconvert/cmd/cbconvert-gui/i18n" "github.com/gen2brain/iup-go/iup" ) @@ -215,13 +216,13 @@ func onProfileSelect(ih iup.Ihandle) int { func onSave(iup.Ihandle) int { name := currentProfile() - if iup.GetParam("Save Profile", nil, "Name: %s\n", &name) != 1 { + if iup.GetParam(i18n.Str(i18n.DlgSaveProfile), nil, i18n.Str(i18n.ParamName), &name) != 1 { return iup.DEFAULT } name = strings.TrimSpace(name) if name == "" || strings.ContainsAny(name, ".;") { - iup.Message("Invalid Name", "Profile name must not be empty or contain '.' or ';'.") + iup.Message(i18n.Str(i18n.MsgInvalidNameTitle), i18n.Str(i18n.MsgInvalidNameBody)) return iup.DEFAULT } diff --git a/cmd/cbconvert-gui/state.go b/cmd/cbconvert-gui/state.go index a298e97..bd26511 100644 --- a/cmd/cbconvert-gui/state.go +++ b/cmd/cbconvert-gui/state.go @@ -1,6 +1,9 @@ package main -import "github.com/gen2brain/iup-go/iup" +import ( + "github.com/gen2brain/cbconvert/cmd/cbconvert-gui/i18n" + "github.com/gen2brain/iup-go/iup" +) func setActive() { if busy { @@ -33,17 +36,17 @@ func setActive() { var tip string switch { case count == 0 && opts.OutDir == "": - active, tip = "NO", "Add files and set output directory" + active, tip = "NO", i18n.Lng(i18n.StatusNeedFilesAndDir) case count == 0: - active, tip = "NO", "Add files" + active, tip = "NO", i18n.Lng(i18n.StatusNeedFiles) case opts.OutDir == "": - active, tip = "NO", "Set output directory" + active, tip = "NO", i18n.Lng(i18n.StatusNeedOutDir) } enabledTip := map[string]string{ - "Thumbnail": "Extract cover thumbnails", - "Cover": "Extract covers", - "Convert": "Convert files to the selected format", + "Thumbnail": i18n.Lng(i18n.TipThumbnail), + "Cover": i18n.Lng(i18n.TipCover), + "Convert": i18n.Lng(i18n.TipConvert), } for _, h := range []string{"Thumbnail", "Cover", "Convert"} { @@ -119,12 +122,12 @@ func setBusy(on bool) { iup.GetHandle(h).SetAttribute("ACTIVE", "NO") } convert.SetAttribute("ACTIVE", "YES") - convert.SetAttribute("TITLE", "Cancel") - convert.SetAttribute("TIP", "Cancel the running operation (or press Esc)") + convert.SetAttribute("TITLE", i18n.Lng(i18n.BtnCancel)) + convert.SetAttribute("TIP", i18n.Lng(i18n.TipCancel)) } else { activeConv = nil - convert.SetAttribute("TITLE", "&Convert") - convert.SetAttribute("TIP", "Convert files to the selected format") + convert.SetAttribute("TITLE", i18n.Lng(i18n.BtnConvert)) + convert.SetAttribute("TIP", i18n.Lng(i18n.TipConvert)) setActive() // restores the conditional buttons and option boxes } } diff --git a/cmd/cbconvert-gui/widgets.go b/cmd/cbconvert-gui/widgets.go index 83c45eb..796dc75 100644 --- a/cmd/cbconvert-gui/widgets.go +++ b/cmd/cbconvert-gui/widgets.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/gen2brain/cbconvert" + "github.com/gen2brain/cbconvert/cmd/cbconvert-gui/i18n" "github.com/gen2brain/iup-go/iup" ) @@ -21,16 +22,16 @@ func setEffort(format string) { switch format { case "webp": val.SetAttributes("MIN=0, MAX=6, SHOWTICKS=7, VALUE=4") - val.SetAttribute("TIP", "WEBP method, higher is better/slower (0-6, default 4)") - name = "Method" + val.SetAttribute("TIP", i18n.Lng(i18n.TipEffortWebp)) + name = i18n.Str(i18n.EffortMethod) case "avif": val.SetAttributes("MIN=0, MAX=10, SHOWTICKS=11, VALUE=10") - val.SetAttribute("TIP", "AVIF speed, higher is faster/worse (0-10, default 10)") - name = "Speed" + val.SetAttribute("TIP", i18n.Lng(i18n.TipEffortAvif)) + name = i18n.Str(i18n.EffortSpeed) case "jxl": val.SetAttributes("MIN=1, MAX=10, SHOWTICKS=10, VALUE=7") - val.SetAttribute("TIP", "JXL effort, higher is better/slower (1-10, default 7)") - name = "Effort" + val.SetAttribute("TIP", i18n.Lng(i18n.TipEffortJxl)) + name = i18n.Str(i18n.EffortEffort) default: return } @@ -56,9 +57,9 @@ func list() iup.Ihandle { "EXPAND": "YES", "NUMCOL": "3", "NUMLIN": "0", - "TITLE1": "Title", - "TITLE2": "Type", - "TITLE3": "Size (MiB)", + "TITLE1": i18n.Lng(i18n.ColTitle), + "TITLE2": i18n.Lng(i18n.ColType), + "TITLE3": i18n.Lng(i18n.ColSize), "WIDTH1": "300", "WIDTH2": "50", "WIDTH3": "100", @@ -186,10 +187,10 @@ func previewMessage(ih iup.Ihandle, s string, i int, p any) int { func pageBox() iup.Ihandle { return iup.Hbox( iup.Space().SetAttribute("SIZE", "5"), - iup.Label("Page:"), + iup.Label(i18n.Lng(i18n.LblPage)), iup.Space().SetAttribute("SIZE", "3"), iup.Text().SetAttributes(`SPIN=YES, SPINMIN=1, SPINMAX=1, VALUE=1, VISIBLECOLUMNS=3, MASK="/d*"`).SetHandle("Page"). - SetAttribute("TIP", "Preview a different page of the selected comic"). + SetAttribute("TIP", i18n.Lng(i18n.TipPage)). SetCallback("SPIN_CB", iup.SpinFunc(func(ih iup.Ihandle, pos int) int { return onPageChanged() })). @@ -212,6 +213,8 @@ func pageBox() iup.Ihandle { } ih.SetAttribute("VALUE", strconv.Itoa(previewPage+1)) + iup.Refresh(iup.GetHandle("PageBox")) + previewRender() return iup.DEFAULT @@ -224,16 +227,16 @@ func pageBox() iup.Ihandle { func tabInput() iup.Ihandle { return iup.Hbox( iup.Vbox( - iup.Toggle(" Recurse SubDirectories").SetHandle("Recursive"). - SetAttributes(`TIP="Process subdirectories recursively"`), - iup.Toggle(" Only Grayscale Images").SetHandle("NoRGB"). - SetAttributes(`TIP="Do not convert images that have RGB colorspace"`), - iup.Toggle(" Exclude Cover").SetHandle("NoCover"). - SetAttributes(`TIP="Do not convert the cover image"`), - iup.Toggle(" Remove Non-Image Files from the Archive").SetHandle("NoNonImage"). - SetAttribute("TIP", "Remove .nfo, .xml, .txt files from the archive"), - iup.Toggle(" Do not Transform or Convert Images").SetHandle("NoConvert"). - SetAttributes(`TIP="Copy images from archive or directory without modifications"`). + iup.Toggle(i18n.Lng(i18n.TglRecursive)).SetHandle("Recursive"). + SetAttribute("TIP", i18n.Lng(i18n.TipRecursive)), + iup.Toggle(i18n.Lng(i18n.TglNoRGB)).SetHandle("NoRGB"). + SetAttribute("TIP", i18n.Lng(i18n.TipNoRGB)), + iup.Toggle(i18n.Lng(i18n.TglNoCover)).SetHandle("NoCover"). + SetAttribute("TIP", i18n.Lng(i18n.TipNoCover)), + iup.Toggle(i18n.Lng(i18n.TglNoNonImage)).SetHandle("NoNonImage"). + SetAttribute("TIP", i18n.Lng(i18n.TipNoNonImage)), + iup.Toggle(i18n.Lng(i18n.TglNoConvert)).SetHandle("NoConvert"). + SetAttribute("TIP", i18n.Lng(i18n.TipNoConvert)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { setActive() @@ -243,12 +246,12 @@ func tabInput() iup.Ihandle { iup.Space().SetAttribute("SIZE", "15"), iup.Vbox( iup.Vbox( - iup.Label("Minimum Size (MiB):"), + iup.Label(i18n.Lng(i18n.LblMinSize)), iup.Text().SetAttributes(`SPIN=YES, SPINMAX=2048, VISIBLECOLUMNS=4, MASK="/d*"`).SetHandle("Size"). - SetAttributes(`TIP="Process only files larger than minimum size"`), + SetAttribute("TIP", i18n.Lng(i18n.TipSize)), ), iup.Vbox( - iup.Label("Document DPI:"), + iup.Label(i18n.Lng(i18n.LblDPI)), iup.List().SetAttributes(map[string]string{ "DROPDOWN": "YES", "EDITBOX": "YES", @@ -260,7 +263,7 @@ func tabInput() iup.Ihandle { "4": "600", "5": "1200", }).SetHandle("DPI"). - SetAttribute("TIP", "Resolution for rendering documents (PDF, EPUB, etc.); Default is 300"), + SetAttribute("TIP", i18n.Lng(i18n.TipDPI)), ), ).SetAttributes("NGAP=10"), ).SetHandle("VboxInput") @@ -270,32 +273,32 @@ func tabOutput() iup.Ihandle { return iup.Hbox( iup.Vbox( iup.Vbox( - iup.Label("Output Directory:"), + iup.Label(i18n.Lng(i18n.LblOutDir)), iup.Text().SetAttributes("VISIBLECOLUMNS=16, MINSIZE=100x").SetHandle("OutDir"). - SetAttribute("TIP", "Directory where converted files are written (required)"). + SetAttribute("TIP", i18n.Lng(i18n.TipOutDir)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { setActive() return iup.DEFAULT })), iup.Space().SetAttribute("SIZE", "5x0"), - iup.Button("Browse...").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + iup.Button(i18n.Lng(i18n.BtnBrowse)).SetAttributes("PADDING=DEFAULTBUTTONPADDING"). SetCallback("ACTION", iup.ActionFunc(onOutputDirectory)), ), iup.Vbox( - iup.Label("Add Suffix to Output File:"), + iup.Label(i18n.Lng(i18n.LblSuffix)), iup.Text().SetAttributes("VISIBLECOLUMNS=16, MINSIZE=100x").SetHandle("Suffix"). - SetAttribute("TIP", "Add suffix to filename, i.e. filename_suffix.cbz"), + SetAttribute("TIP", i18n.Lng(i18n.TipSuffix)), ), iup.Vbox( - iup.Label("Archive Format:"), + iup.Label(i18n.Lng(i18n.LblArchive)), iup.List().SetAttributes(map[string]string{ "DROPDOWN": "YES", "VALUE": "1", "1": "ZIP", "2": "TAR", }).SetHandle("Archive"). - SetAttribute("TIP", "Output container: ZIP (.cbz) or uncompressed TAR (.cbt)"). + SetAttribute("TIP", i18n.Lng(i18n.TipArchive)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { setActive() @@ -303,7 +306,7 @@ func tabOutput() iup.Ihandle { })), ), iup.Vbox( - iup.Label("Compression:"), + iup.Label(i18n.Lng(i18n.LblCompression)), iup.List().SetAttributes(map[string]string{ "DROPDOWN": "YES", "VALUE": "1", @@ -319,14 +322,14 @@ func tabOutput() iup.Ihandle { "10": "8", "11": "9", }).SetHandle("ZipLevel"). - SetAttribute("TIP", "ZIP compression: Store disables it, 1 is fastest, 9 is smallest"), + SetAttribute("TIP", i18n.Lng(i18n.TipZipLevel)), ).SetHandle("VboxZipLevel"), ).SetAttributes("NGAP=10"), iup.Space().SetAttribute("SIZE", "15"), iup.Vbox( iup.Vbox( - iup.Toggle(" Combine into single file").SetHandle("Combine"). - SetAttributes(`TIP="Merge all listed files into one archive"`). + iup.Toggle(i18n.Lng(i18n.TglCombine)).SetHandle("Combine"). + SetAttribute("TIP", i18n.Lng(i18n.TipCombine)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { setActive() @@ -334,11 +337,11 @@ func tabOutput() iup.Ihandle { })), ), iup.Vbox( - iup.Label("Output File:"), + iup.Label(i18n.Lng(i18n.LblOutFile)), iup.Text().SetAttributes("VISIBLECOLUMNS=16, MINSIZE=100x").SetHandle("OutFile"). - SetAttribute("TIP", "Combined file name (default: first input + -combined)"), + SetAttribute("TIP", i18n.Lng(i18n.TipOutFile)), iup.Space().SetAttribute("SIZE", "5x0"), - iup.Button("Browse...").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + iup.Button(i18n.Lng(i18n.BtnBrowse)).SetAttributes("PADDING=DEFAULTBUTTONPADDING"). SetCallback("ACTION", iup.ActionFunc(onOutputFile)), ).SetHandle("VboxOutFile"), ).SetAttributes("NGAP=10"), @@ -349,7 +352,7 @@ func tabImage() iup.Ihandle { return iup.Hbox( iup.Vbox( iup.Vbox( - iup.Label("Format:"), + iup.Label(i18n.Lng(i18n.LblFormat)), iup.List().SetAttributes(map[string]string{ "DROPDOWN": "YES", "VALUE": "1", @@ -361,7 +364,7 @@ func tabImage() iup.Ihandle { "6": "AVIF", "7": "JXL", }).SetHandle("Format"). - SetAttribute("TIP", "Output image format for the converted pages"). + SetAttribute("TIP", i18n.Lng(i18n.TipFormat)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { setEffort(strings.ToLower(ih.GetAttribute("VALUESTRING"))) setActive() @@ -371,10 +374,11 @@ func tabImage() iup.Ihandle { })), ), iup.Vbox( - iup.Label("Size:"), + iup.Label(i18n.Lng(i18n.LblSize)), iup.Hbox( - iup.Text().SetAttributes(`CUEBANNER="width", VISIBLECOLUMNS=6, MASK="/d*"`).SetHandle("Width"). - SetAttribute("TIP", "If one of, width or height is not set, the image aspect ratio is preserved"). + iup.Text().SetAttributes(`VISIBLECOLUMNS=6, MASK="/d*"`).SetHandle("Width"). + SetAttribute("CUEBANNER", i18n.Lng(i18n.CueWidth)). + SetAttribute("TIP", i18n.Lng(i18n.TipWidthHeight)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { setActive() ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) @@ -392,8 +396,9 @@ func tabImage() iup.Ihandle { iup.Space().SetAttribute("SIZE", "2"), iup.Label("x"), iup.Space().SetAttribute("SIZE", "2"), - iup.Text().SetAttributes(`CUEBANNER="height", VISIBLECOLUMNS=6, MASK="/d*"`).SetHandle("Height"). - SetAttribute("TIP", "If one of, width or height is not set, the image aspect ratio is preserved"). + iup.Text().SetAttributes(`VISIBLECOLUMNS=6, MASK="/d*"`).SetHandle("Height"). + SetAttribute("CUEBANNER", i18n.Lng(i18n.CueHeight)). + SetAttribute("TIP", i18n.Lng(i18n.TipWidthHeight)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { setActive() ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) @@ -411,17 +416,17 @@ func tabImage() iup.Ihandle { ).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=0"), ), iup.Vbox( - iup.Toggle(" Best Fit").SetHandle("Fit"). - SetAttributes(`TIP="Best fit for required width and height"`), - iup.Toggle(" No Upscale").SetHandle("NoUpscale"). - SetAttribute("TIP", "Do not enlarge images already smaller than the requested size"), + iup.Toggle(i18n.Lng(i18n.TglFit)).SetHandle("Fit"). + SetAttribute("TIP", i18n.Lng(i18n.TipFit)), + iup.Toggle(i18n.Lng(i18n.TglNoUpscale)).SetHandle("NoUpscale"). + SetAttribute("TIP", i18n.Lng(i18n.TipNoUpscale)), ), iup.Vbox( - iup.Label("Resize Filter:"), + iup.Label(i18n.Lng(i18n.LblFilter)), iup.List().SetAttributes(map[string]string{ "DROPDOWN": "YES", "VALUE": "3", - "TIP": "Linear is the bilinear filter, smooth and reasonably fast", + "TIP": i18n.Lng(i18n.FilterLinear), "1": "NearestNeighbor", "2": "Box", "3": "Linear", @@ -436,11 +441,11 @@ func tabImage() iup.Ihandle { iup.Vbox( iup.Vbox( iup.Hbox( - iup.Label("Quality: "), + iup.Label(i18n.Lng(i18n.LblQuality)), iup.Label("75").SetHandle("LabelQuality"), ).SetAttributes("NMARGIN=0"), iup.Val("").SetAttributes(`MIN=0, MAX=100, VALUE=75, SHOWTICKS=10`).SetHandle("Quality"). - SetAttribute("TIP", "Quality affects JPEG, WEBP, AVIF and JXL"). + SetAttribute("TIP", i18n.Lng(i18n.TipQuality)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { iup.GetHandle("LabelQuality").SetAttribute("TITLE", ih.GetInt("VALUE")) iup.Refresh(iup.GetHandle("LabelQuality")) @@ -458,9 +463,9 @@ func tabImage() iup.Ihandle { })), ).SetHandle("VboxQuality"), iup.Vbox( - iup.Label("Effort:").SetHandle("LabelEffort"), + iup.Label(i18n.Lng(i18n.LblEffort)).SetHandle("LabelEffort"), iup.Val("").SetAttributes(`MIN=0, MAX=10, VALUE=0, SHOWTICKS=11`).SetHandle("Effort"). - SetAttribute("TIP", "Encoder speed/effort (WEBP, AVIF, JXL)"). + SetAttribute("TIP", i18n.Lng(i18n.TipEffort)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { iup.GetHandle("LabelEffort").SetAttribute("TITLE", fmt.Sprintf("%s: %d", ih.GetAttribute("EFFORTNAME"), ih.GetInt("VALUE"))) iup.Refresh(iup.GetHandle("LabelEffort")) @@ -478,8 +483,8 @@ func tabImage() iup.Ihandle { })), ).SetHandle("VboxEffort"), iup.Vbox( - iup.Toggle(" Lossless").SetHandle("Lossless"). - SetAttributes(`TIP="Lossless compression (WEBP, AVIF, JXL), ignores quality"`). + iup.Toggle(i18n.Lng(i18n.TglLossless)).SetHandle("Lossless"). + SetAttribute("TIP", i18n.Lng(i18n.TipLossless)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { setActive() previewPost() @@ -488,8 +493,8 @@ func tabImage() iup.Ihandle { })), ), iup.Vbox( - iup.Toggle(" Grayscale").SetHandle("Grayscale"). - SetAttributes(`TIP="Convert images to grayscale (monochromatic)"`). + iup.Toggle(i18n.Lng(i18n.TglGrayscale)).SetHandle("Grayscale"). + SetAttribute("TIP", i18n.Lng(i18n.TipGrayscale)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { previewPost() @@ -504,11 +509,11 @@ func tabTransform() iup.Ihandle { return iup.Vbox( iup.Vbox( iup.Hbox( - iup.Label("Brightness: "), + iup.Label(i18n.Lng(i18n.LblBrightness)), iup.Label("0").SetHandle("LabelBrightness"), ).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=0"), iup.Val("").SetAttributes(`MIN=-100, MAX=100, VALUE=0, SHOWTICKS=10`).SetHandle("Brightness"). - SetAttributes(`TIP="Adjust the brightness of the images"`). + SetAttribute("TIP", i18n.Lng(i18n.TipBrightness)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { iup.GetHandle("LabelBrightness").SetAttribute("TITLE", iup.GetHandle("Brightness").GetInt("VALUE")) iup.Refresh(iup.GetHandle("LabelBrightness")) @@ -527,11 +532,11 @@ func tabTransform() iup.Ihandle { ), iup.Vbox( iup.Hbox( - iup.Label("Contrast: "), + iup.Label(i18n.Lng(i18n.LblContrast)), iup.Label("0").SetHandle("LabelContrast"), ).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=0"), iup.Val("").SetAttributes(`MIN=-100, MAX=100, VALUE=0, SHOWTICKS=10`).SetHandle("Contrast"). - SetAttributes(`TIP="Adjust the contrast of the images"`). + SetAttribute("TIP", i18n.Lng(i18n.TipContrast)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { iup.GetHandle("LabelContrast").SetAttribute("TITLE", iup.GetHandle("Contrast").GetInt("VALUE")) iup.Refresh(iup.GetHandle("LabelContrast")) @@ -549,7 +554,7 @@ func tabTransform() iup.Ihandle { })), ), iup.Vbox( - iup.Label("Rotate:"), + iup.Label(i18n.Lng(i18n.LblRotate)), iup.List().SetAttributes(map[string]string{ "DROPDOWN": "YES", "VALUE": "1", @@ -558,7 +563,7 @@ func tabTransform() iup.Ihandle { "3": "180", "4": "270", }).SetHandle("Rotate"). - SetAttribute("TIP", "Rotate every page clockwise by the given angle in degrees"). + SetAttribute("TIP", i18n.Lng(i18n.TipRotate)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { previewPost() @@ -570,41 +575,41 @@ func tabTransform() iup.Ihandle { func tabs() iup.Ihandle { return iup.Tabs( - tabInput().SetAttributes("TABTITLE=Input, NMARGIN=10x10"), - tabOutput().SetAttributes("TABTITLE=Output, NMARGIN=10x10"), - tabImage().SetAttributes("TABTITLE=Image, NMARGIN=10x10"), - tabTransform().SetAttributes("TABTITLE=Transform, NMARGIN=10x10"), + tabInput().SetAttributes("TABTITLE="+i18n.Lng(i18n.TabInput)+", NMARGIN=10x10"), + tabOutput().SetAttributes("TABTITLE="+i18n.Lng(i18n.TabOutput)+", NMARGIN=10x10"), + tabImage().SetAttributes("TABTITLE="+i18n.Lng(i18n.TabImage)+", NMARGIN=10x10"), + tabTransform().SetAttributes("TABTITLE="+i18n.Lng(i18n.TabTransform)+", NMARGIN=10x10"), ).SetHandle("Tabs") } func buttons() iup.Ihandle { - addFiles := iup.Button("Add &Files...").SetHandle("AddFiles").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + addFiles := iup.Button(i18n.Lng(i18n.BtnAddFiles)).SetHandle("AddFiles").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). SetCallback("ACTION", iup.ActionFunc(onAddFiles)) - addDir := iup.Button("Add &Dir...").SetHandle("AddDir").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + addDir := iup.Button(i18n.Lng(i18n.BtnAddDir)).SetHandle("AddDir").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). SetCallback("ACTION", iup.ActionFunc(onAddDir)) - remove := iup.Button("Remove").SetHandle("Remove").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + remove := iup.Button(i18n.Lng(i18n.BtnRemove)).SetHandle("Remove").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). SetCallback("ACTION", iup.ActionFunc(onRemove)) - removeAll := iup.Button("Remove All").SetHandle("RemoveAll").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + removeAll := iup.Button(i18n.Lng(i18n.BtnRemoveAll)).SetHandle("RemoveAll").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). SetCallback("ACTION", iup.ActionFunc(onRemoveAll)) - thumbnail := iup.Button("Thumbnail").SetHandle("Thumbnail").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + thumbnail := iup.Button(i18n.Lng(i18n.BtnThumbnail)).SetHandle("Thumbnail").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). SetCallback("ACTION", iup.ActionFunc(onThumbnail)) - cover := iup.Button("Cover").SetHandle("Cover").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + cover := iup.Button(i18n.Lng(i18n.BtnCover)).SetHandle("Cover").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). SetCallback("ACTION", iup.ActionFunc(onCover)) - convert := iup.Button("&Convert").SetHandle("Convert").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + convert := iup.Button(i18n.Lng(i18n.BtnConvert)).SetHandle("Convert").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). SetCallback("ACTION", iup.ActionFunc(onConvert)) - reset := iup.Button("Reset").SetHandle("Reset").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). - SetAttribute("TIP", "Restore all settings to their defaults"). + reset := iup.Button(i18n.Lng(i18n.BtnReset)).SetHandle("Reset").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + SetAttribute("TIP", i18n.Lng(i18n.TipReset)). SetCallback("ACTION", iup.ActionFunc(onReset)) - save := iup.Button("Save").SetHandle("Save").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). - SetAttribute("TIP", "Save current settings to a profile"). + save := iup.Button(i18n.Lng(i18n.BtnSave)).SetHandle("Save").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + SetAttribute("TIP", i18n.Lng(i18n.TipSave)). SetCallback("ACTION", iup.ActionFunc(onSave)) - command := iup.Button("Command").SetHandle("Command").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). - SetAttribute("TIP", "Show the equivalent command line"). + command := iup.Button(i18n.Lng(i18n.BtnCommand)).SetHandle("Command").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + SetAttribute("TIP", i18n.Lng(i18n.TipCommand)). SetCallback("ACTION", iup.ActionFunc(onCommand)) profile := iup.List().SetAttributes("DROPDOWN=YES").SetHandle("Profile"). - SetAttribute("TIP", "Select a settings profile"). + SetAttribute("TIP", i18n.Lng(i18n.TipProfile)). SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(onProfileSelect)) iup.Normalizer(addFiles, addDir, remove, removeAll, thumbnail, cover, convert, reset, save, command).SetAttribute("NORMALIZE", "BOTH") @@ -628,7 +633,7 @@ func buttons() iup.Ihandle { ), iup.Fill(), iup.Vbox( - iup.Label("Profile:"), + iup.Label(i18n.Lng(i18n.LblProfile)), profile, reset, save, @@ -654,7 +659,7 @@ func status() iup.Ihandle { ih.SetAttributes("VALUE=0, VISIBLE=YES") ih.SetAttribute("MAX", conv.Ncontents) - iup.GetHandle("LabelStatus1").SetAttribute("TITLE", fmt.Sprintf("File %d of %d", conv.CurrFile, conv.Nfiles)) + iup.GetHandle("LabelStatus1").SetAttribute("TITLE", fmt.Sprintf(i18n.Str(i18n.StatusFileOf), conv.CurrFile, conv.Nfiles)) iup.GetHandle("LabelStatus1").SetAttributes("VISIBLE=YES") iup.GetHandle("LabelStatus2").SetAttributes("VISIBLE=YES")