build: allow disabling i18n

GNU gettext simply is a PITA on certain platforms (i.e. Windows, musl
Linux, etc.) and currently it's not possible to cleanly remove i18n
from the build process, making building Ghostty on the aforementioned
platforms difficult. By providing users with a way to opt-out of the
i18n mechanisms (or opt-in, on platforms where i18n is disabled by
default) we can make sure that people at least have *some* way of
building Ghostty before i18n mechanisms can be integrated neatly.
pull/8158/head
Leah Amelia Chen 2025-08-06 14:44:40 +08:00
parent c2165fc097
commit 5fbdb8c459
No known key found for this signature in database
5 changed files with 33 additions and 9 deletions

View File

@ -27,7 +27,7 @@ pub fn build(b: *std.Build) !void {
// Ghostty resources like terminfo, shell integration, themes, etc.
const resources = try buildpkg.GhosttyResources.init(b, &config);
const i18n = try buildpkg.GhosttyI18n.init(b, &config);
const i18n = if (config.i18n) try buildpkg.GhosttyI18n.init(b, &config) else null;
// Ghostty dependencies used by many artifacts.
const deps = try buildpkg.SharedDeps.init(b, &config);
@ -79,7 +79,7 @@ pub fn build(b: *std.Build) !void {
if (config.app_runtime != .none) {
exe.install();
resources.install();
i18n.install();
if (i18n) |v| v.install();
} else {
// Libghostty
//
@ -112,7 +112,7 @@ pub fn build(b: *std.Build) !void {
// The xcframework build always installs resources because our
// macOS xcode project contains references to them.
resources.install();
i18n.install();
if (i18n) |v| v.install();
}
// Ghostty macOS app
@ -122,7 +122,7 @@ pub fn build(b: *std.Build) !void {
.{
.xcframework = &xcframework,
.docs = &docs,
.i18n = &i18n,
.i18n = if (i18n) |v| &v else null,
.resources = &resources,
},
);
@ -166,7 +166,7 @@ pub fn build(b: *std.Build) !void {
.{
.xcframework = &xcframework_native,
.docs = &docs,
.i18n = &i18n,
.i18n = if (i18n) |v| &v else null,
.resources = &resources,
},
);
@ -204,5 +204,9 @@ pub fn build(b: *std.Build) !void {
// update-translations does what it sounds like and updates the "pot"
// files. These should be committed to the repo.
translations_step.dependOn(i18n.update_step);
if (i18n) |v| {
translations_step.dependOn(v.update_step);
} else {
try translations_step.addError("cannot update translations when i18n is disabled", .{});
}
}

View File

@ -37,6 +37,7 @@ font_backend: font.Backend = .freetype,
x11: bool = false,
wayland: bool = false,
sentry: bool = true,
i18n: bool = true,
wasm_shared: bool = true,
/// Ghostty exe properties
@ -175,6 +176,16 @@ pub fn init(b: *std.Build) !Config {
"Enables linking against X11 libraries when using the GTK rendering backend.",
) orelse gtk_targets.x11;
config.i18n = b.option(
bool,
"i18n",
"Enables gettext-based internationalization. Enabled by default only for macOS, and other Unix-like systems like Linux and FreeBSD when using glibc.",
) orelse switch (target.result.os.tag) {
.macos, .ios => true,
.linux, .freebsd => target.result.isGnuLibC(),
else => false,
};
//---------------------------------------------------------------
// Ghostty Exe Properties
@ -420,6 +431,7 @@ pub fn addOptions(self: *const Config, step: *std.Build.Step.Options) !void {
step.addOption(bool, "x11", self.x11);
step.addOption(bool, "wayland", self.wayland);
step.addOption(bool, "sentry", self.sentry);
step.addOption(bool, "i18n", self.i18n);
step.addOption(apprt.Runtime, "app_runtime", self.app_runtime);
step.addOption(font.Backend, "font_backend", self.font_backend);
step.addOption(rendererpkg.Impl, "renderer", self.renderer);
@ -467,6 +479,7 @@ pub fn fromOptions() Config {
.exe_entrypoint = std.meta.stringToEnum(ExeEntrypoint, @tagName(options.exe_entrypoint)).?,
.wasm_target = std.meta.stringToEnum(WasmTarget, @tagName(options.wasm_target)).?,
.wasm_shared = options.wasm_shared,
.i18n = options.i18n,
};
}

View File

@ -17,7 +17,7 @@ xctest: *std.Build.Step.Run,
pub const Deps = struct {
xcframework: *const XCFramework,
docs: *const Docs,
i18n: *const I18n,
i18n: ?*const I18n,
resources: *const Resources,
};
@ -81,7 +81,7 @@ pub fn init(
// We also need all these resources because the xcode project
// references them via symlinks.
deps.resources.addStepDependencies(&step.step);
deps.i18n.addStepDependencies(&step.step);
if (deps.i18n) |v| v.addStepDependencies(&step.step);
deps.docs.installDummy(&step.step);
// Expect success
@ -113,7 +113,7 @@ pub fn init(
// We also need all these resources because the xcode project
// references them via symlinks.
deps.resources.addStepDependencies(&step.step);
deps.i18n.addStepDependencies(&step.step);
if (deps.i18n) |v| v.addStepDependencies(&step.step);
deps.docs.installDummy(&step.step);
// Expect success

View File

@ -41,6 +41,7 @@ pub const flatpak = options.flatpak;
pub const app_runtime: apprt.Runtime = config.app_runtime;
pub const font_backend: font.Backend = config.font_backend;
pub const renderer: rendererpkg.Impl = config.renderer;
pub const i18n: bool = config.i18n;
/// The bundle ID for the app. This is used in many places and is currently
/// hardcoded here. We could make this configurable in the future if there

View File

@ -73,6 +73,8 @@ pub const InitError = error{
/// want to set the domain for the entire application since this is also
/// used by libghostty.
pub fn init(resources_dir: []const u8) InitError!void {
if (comptime !build_config.i18n) return;
switch (builtin.os.tag) {
// i18n is unsupported on Windows
.windows => return,
@ -102,11 +104,13 @@ pub fn init(resources_dir: []const u8) InitError!void {
/// This should only be called for apprts that are fully owning the
/// Ghostty application. This should not be called for libghostty users.
pub fn initGlobalDomain() error{OutOfMemory}!void {
if (comptime !build_config.i18n) return;
_ = textdomain(build_config.bundle_id) orelse return error.OutOfMemory;
}
/// Translate a message for the Ghostty domain.
pub fn _(msgid: [*:0]const u8) [*:0]const u8 {
if (comptime !build_config.i18n) return msgid;
return dgettext(build_config.bundle_id, msgid);
}
@ -132,6 +136,8 @@ pub fn canonicalizeLocale(
buf: []u8,
locale: []const u8,
) error{NoSpaceLeft}![:0]const u8 {
if (comptime !build_config.i18n) return locale;
// Fix zh locales for macOS
if (fixZhLocale(locale)) |fixed| return fixed;