diff --git a/src/global.zig b/src/global.zig index b9af5983d..c93b35fa0 100644 --- a/src/global.zig +++ b/src/global.zig @@ -172,6 +172,11 @@ pub const GlobalState = struct { // hereafter can use this cached value. self.resources_dir = try internal_os.resourcesDir(self.alloc); errdefer if (self.resources_dir) |dir| self.alloc.free(dir); + + // Setup i18n + if (self.resources_dir) |v| internal_os.i18n.init(v) catch |err| { + std.log.warn("failed to init i18n, translations will not be available err={}", .{err}); + }; } /// Cleans up the global state. This doesn't _need_ to be called but diff --git a/src/os/i18n.zig b/src/os/i18n.zig new file mode 100644 index 000000000..d6124cac5 --- /dev/null +++ b/src/os/i18n.zig @@ -0,0 +1,38 @@ +const std = @import("std"); +const build_config = @import("../build_config.zig"); + +pub const InitError = error{ + InvalidResourcesDir, + OutOfMemory, +}; + +/// Initialize i18n support for the application. This should be +/// called automatically by the global state initialization +/// in global.zig. +/// +/// This calls `bindtextdomain` for gettext with the proper directory +/// of translations. This does NOT call `textdomain` as we don't +/// 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 { + // Our resources dir is always nested below the share dir that + // is standard for translations. + const share_dir = std.fs.path.dirname(resources_dir) orelse + return error.InvalidResourcesDir; + + // Build our locale path + var buf: [std.fs.max_path_bytes]u8 = undefined; + const path = std.fmt.bufPrintZ(&buf, "{s}/locale", .{share_dir}) catch + return error.OutOfMemory; + + // Bind our bundle ID to the given locale path + _ = bindtextdomain(build_config.bundle_id, path.ptr) orelse + return error.OutOfMemory; +} + +// Manually include function definitions for the gettext functions +// as libintl.h isn't always easily available (e.g. in musl) +extern fn bindtextdomain(domainname: [*:0]const u8, dirname: [*:0]const u8) ?[*:0]const u8; +extern fn textdomain(domainname: [*:0]const u8) ?[*:0]const u8; +pub extern fn gettext(msgid: [*:0]const u8) [*:0]const u8; +pub const _ = gettext; diff --git a/src/os/main.zig b/src/os/main.zig index cb9355931..7c961ea13 100644 --- a/src/os/main.zig +++ b/src/os/main.zig @@ -17,6 +17,7 @@ const resourcesdir = @import("resourcesdir.zig"); pub const args = @import("args.zig"); pub const cgroup = @import("cgroup.zig"); pub const hostname = @import("hostname.zig"); +pub const i18n = @import("i18n.zig"); pub const passwd = @import("passwd.zig"); pub const xdg = @import("xdg.zig"); pub const windows = @import("windows.zig");