Skip to content

Commit

Permalink
feat: initial implementation of i18n/l10n
Browse files Browse the repository at this point in the history
  • Loading branch information
pluiedev committed Feb 3, 2025
1 parent c5508e7 commit d393217
Show file tree
Hide file tree
Showing 19 changed files with 467 additions and 49 deletions.
1 change: 1 addition & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
.freetype = .{ .path = "./pkg/freetype" },
.harfbuzz = .{ .path = "./pkg/harfbuzz" },
.highway = .{ .path = "./pkg/highway" },
.libintl = .{ .path = "./pkg/libintl" },
.libpng = .{ .path = "./pkg/libpng" },
.macos = .{ .path = "./pkg/macos" },
.oniguruma = .{ .path = "./pkg/oniguruma" },
Expand Down
2 changes: 2 additions & 0 deletions nix/devShell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
wayland,
wayland-scanner,
wayland-protocols,
gettext,
}: let
# See package.nix. Keep in sync.
rpathLibs =
Expand Down Expand Up @@ -84,6 +85,7 @@
gtk4
glib
wayland
gettext
];
in
mkShell {
Expand Down
3 changes: 3 additions & 0 deletions nix/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
pkg-config,
zig_0_13,
pandoc,
gettext,
revision ? "dirty",
optimize ? "Debug",
enableX11 ? true,
Expand Down Expand Up @@ -56,6 +57,7 @@
../images
../include
../pkg
../po
../src
../vendor
../build.zig
Expand Down Expand Up @@ -125,6 +127,7 @@ in
pkg-config
zig_hook
wrapGAppsHook4
gettext
]
++ lib.optionals enableWayland [
wayland-scanner
Expand Down
42 changes: 42 additions & 0 deletions pkg/libintl/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const std = @import("std");

pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

const module = b.addModule("intl", .{
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = optimize,
});

if (target.result.isGnuLibC()) {
// If we use glibc, then great! We don't have to do anything.
// lib.linkLibC();
} else {
// If we're on any other platform we have to do more work.
// In GNU's infinite wisdom, there's no easy pkg-config file for
// you to consume and integrate into build systems other than autoconf.
// Users must rely on system library/include paths, or manually
// add libintl to the Zig search path.

switch (target.result.os.tag) {
// .windows => {
// const msys2 = b.dependency("libintl_msys2", .{});
// lib.addLibraryPath(msys2.path("usr/bin"));
// module.linkSystemLibrary2("msys-intl-8", .{
// .preferred_link_mode = .dynamic,
// .search_strategy = .mode_first,
// });
// },
else => |tag| if (tag.isDarwin()) {
// module.linkSystemLibrary2("libintl", .{
// .preferred_link_mode = .dynamic,
// .search_strategy = .mode_first,
// });
} else {
@compileError("unsupported platform");
},
}
}
}
6 changes: 6 additions & 0 deletions pkg/libintl/build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.{
.name = "libintl",
.version = "0.0.1",
.paths = .{""},
.dependencies = .{},
}
41 changes: 41 additions & 0 deletions pkg/libintl/c.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
pub const locale = @cImport(@cInclude("locale.h"));

pub extern fn gettext(
msgid: [*:0]const u8,
) [*:0]const u8;
pub extern fn dgettext(
domainname: [*:0]const u8,
msgid: [*:0]const u8,
) [*:0]const u8;
pub extern fn dcgettext(
domainname: [*:0]const u8,
msgid: [*:0]const u8,
category: c_int,
) [*:0]const u8;

pub extern fn ngettext(
msgid1: [*:0]const u8,
msgid2: [*:0]const u8,
n: c_ulong,
) [*:0]const u8;
pub extern fn dngettext(
domainname: [*:0]const u8,
msgid1: [*:0]const u8,
msgid2: [*:0]const u8,
n: c_ulong,
) [*:0]const u8;
pub extern fn dcngettext(
domainname: [*:0]const u8,
msgid1: [*:0]const u8,
msgid2: [*:0]const u8,
n: c_ulong,
category: c_int,
) [*:0]const u8;

pub extern fn bindtextdomain(
domainname: [*:0]const u8,
dirname: [*:0]const u8,
) ?[*]const u8;
pub extern fn textdomain(
domainname: ?[*:0]const u8,
) ?[*]const u8;
63 changes: 63 additions & 0 deletions pkg/libintl/main.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const std = @import("std");
const c = @import("c.zig");

pub const Category = enum(c_int) {
messages = c.locale.LC_MESSAGES,
collate = c.locale.LC_COLLATE,
ctype = c.locale.LC_CTYPE,
monetary = c.locale.LC_MONETARY,
numeric = c.locale.LC_NUMERIC,
time = c.locale.LC_TIME,
_,
};

pub const Query = struct {
msg: [:0]const u8,
plural: ?struct {
msg: [:0]const u8,
number: c_ulong,
} = null,
domain: ?[:0]const u8 = null,
category: ?Category = null,
};

pub fn _(msg: [:0]const u8) [:0]const u8 {
return get(.{ .msg = msg });
}

pub fn get(comptime query: Query) [:0]const u8 {
const result = res: {
if (query.plural) |plural| {
if (query.domain) |d| {
break :res if (query.category) |cat|
c.dcngettext(d, query.msg, plural.msg, plural.number, @intFromEnum(cat))
else
c.dngettext(d, query.msg, plural.msg, plural.number);
}

if (query.category != null) @panic("domain must be specified alongside category");
break :res c.ngettext(query.msg, query.plural, plural.number);
}

if (query.domain) |d| {
break :res if (query.category) |cat|
c.dcgettext(d, query.msg, @intFromEnum(cat))
else
c.dgettext(d, query.msg);
}

if (query.category != null) @panic("domain must be specified alongside category");
break :res c.gettext(query.msg);
};

return std.mem.span(result);
}

pub fn bindTextDomain(domain: [:0]const u8, dir: [:0]const u8) std.mem.Allocator.Error!void {
// ENOMEM is the only possible error
if (c.bindtextdomain(domain, dir) == null) return error.OutOfMemory;
}
pub fn setTextDomain(domain: [:0]const u8) std.mem.Allocator.Error!void {
// ENOMEM is the only possible error
if (c.textdomain(domain) == null) return error.OutOfMemory;
}
Empty file added po/LINGUAS
Empty file.
159 changes: 159 additions & 0 deletions po/messages.pot
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
msgid ""
msgstr ""
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: src/apprt/gtk/App.zig:1843 src/apprt/gtk/Window.zig:899
msgid "About Ghostty"
msgstr ""

#: src/apprt/gtk/Tab.zig:147
msgid "All terminal sessions in this tab will be terminated."
msgstr ""

#: src/apprt/gtk/Window.zig:781
msgid "All terminal sessions in this window will be terminated."
msgstr ""

#: src/apprt/gtk/ClipboardConfirmationWindow.zig:170
msgid "Allow"
msgstr ""

#: src/apprt/gtk/ClipboardConfirmationWindow.zig:248
msgid ""
"An application is attempting to read from the clipboard.\n"
"The current clipboard contents are shown below.\n"
msgstr ""

#: src/apprt/gtk/ClipboardConfirmationWindow.zig:252
msgid ""
"An application is attempting to write to the clipboard.\n"
"The content to write is shown below.\n"
msgstr ""

#: src/apprt/gtk/ClipboardConfirmationWindow.zig:237
msgid "Authorize Clipboard Access"
msgstr ""

#: src/apprt/gtk/ClipboardConfirmationWindow.zig:169
msgid "Cancel"
msgstr ""

#: src/apprt/gtk/App.zig:1830
msgid "Close Tab"
msgstr ""

#: src/apprt/gtk/App.zig:1833
msgid "Close Window"
msgstr ""

#: src/apprt/gtk/Tab.zig:143
msgid "Close this tab?"
msgstr ""

#: src/apprt/gtk/Surface.zig:732
msgid "Close this terminal?"
msgstr ""

#: src/apprt/gtk/Window.zig:777
msgid "Close this window?"
msgstr ""

#: src/apprt/gtk/Surface.zig:1145
msgid "Copied to clipboard"
msgstr ""

#: src/apprt/gtk/App.zig:1864
msgid "Copy"
msgstr ""

#: src/apprt/gtk/ClipboardConfirmationWindow.zig:170
msgid "Deny"
msgstr ""

#: src/apprt/gtk/Window.zig:880
msgid "Ghostty Developers"
msgstr ""

#: src/apprt/gtk/inspector.zig:143
msgid "Ghostty: Terminal Inspector"
msgstr ""

#: src/apprt/gtk/App.zig:1890
msgid "Menu"
msgstr ""

#: src/apprt/gtk/App.zig:1829 src/apprt/gtk/Window.zig:201
msgid "New Tab"
msgstr ""

#: src/apprt/gtk/App.zig:1828
msgid "New Window"
msgstr ""

#: src/apprt/gtk/App.zig:1841
msgid "Open Configuration"
msgstr ""

#: src/apprt/gtk/App.zig:1865 src/apprt/gtk/ClipboardConfirmationWindow.zig:169
msgid "Paste"
msgstr ""

#: src/apprt/gtk/ClipboardConfirmationWindow.zig:245
msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some commands may be executed.\n"
msgstr ""

#: src/apprt/gtk/App.zig:1842
msgid "Reload Configuration"
msgstr ""

#: src/apprt/gtk/App.zig:1880
msgid "Reset"
msgstr ""

#: src/apprt/gtk/App.zig:1832 src/apprt/gtk/App.zig:1873
msgid "Split Down"
msgstr ""

#: src/apprt/gtk/App.zig:1831 src/apprt/gtk/App.zig:1872
msgid "Split Right"
msgstr ""

#: src/apprt/gtk/App.zig:1840 src/apprt/gtk/App.zig:1881
msgid "Terminal Inspector"
msgstr ""

#: src/apprt/gtk/Surface.zig:736
msgid ""
"There is still a running process in the terminal. Closing the terminal will kill this process.\n"
"Are you sure you want to close the terminal?\n"
"\n"
"Click 'No' to cancel and return to your terminal.\n"
msgstr ""

#: src/apprt/gtk/Window.zig:174
msgid "View Open Tabs"
msgstr ""

#: src/apprt/gtk/ClipboardConfirmationWindow.zig:236
msgid "Warning: Potentially Unsafe Paste"
msgstr ""

#: src/apprt/gtk/ResizeOverlay.zig:99
msgid "c"
msgid_plural "c"
msgstr[0] ""
msgstr[1] ""

#: src/apprt/gtk/ResizeOverlay.zig:100
msgid "r"
msgid_plural "r"
msgstr[0] ""
msgstr[1] ""

#: src/apprt/gtk/Window.zig:220
msgid "⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
Loading

0 comments on commit d393217

Please sign in to comment.