diff --git a/po/README_CONTRIBUTORS.md b/po/README_CONTRIBUTORS.md index e232c0620..46dad96f9 100644 --- a/po/README_CONTRIBUTORS.md +++ b/po/README_CONTRIBUTORS.md @@ -44,6 +44,30 @@ else const label = gtk.Label.new(text); ``` +If a string must be stored untranslated and only translated later, use +`i18n.N_` instead. This marks the string for extraction into the translation +template but returns the original msgid unchanged. A common use case is +compile-time or static metadata that is translated only when it is presented +to the user. + +```zig +const i18n = @import("i18n.zig"); + +const Command = struct { + title: [:0]const u8, +}; + +const cmd = Command{ + .title = i18n.N_("Reset Terminal"), +}; + +const label = gtk.Label.new(i18n._(cmd.title)); +``` + +If `i18n._` is called at comptime, it returns the original msgid unchanged +while still marking the string for translation. For strings that are stored +untranslated and translated later, prefer `i18n.N_`. + All translatable strings are extracted into the _translation template file_, located under `po/com.mitchellh.ghostty.pot`. **This file must stay in sync with the list of translatable strings present in source code or Blueprints at all times.** diff --git a/src/os/i18n.zig b/src/os/i18n.zig index 88b7b5bf5..20d3c1b97 100644 --- a/src/os/i18n.zig +++ b/src/os/i18n.zig @@ -62,8 +62,13 @@ pub fn initGlobalDomain() error{OutOfMemory}!void { } /// Translate a message for the Ghostty domain. +/// +/// If this is called at comptime, the direct msgid is returned without +/// translation. This still allows the string to be marked for translation +/// while remaining usable in comptime contexts. pub fn _(msgid: [*:0]const u8) [*:0]const u8 { if (comptime !build_config.i18n) return msgid; + if (@inComptime()) return msgid; return dgettext(build_config.bundle_id, msgid); } @@ -196,3 +201,10 @@ test "canonicalizeLocale darwin" { // underscores. We should parse them out before calling this function. try testing.expectEqualStrings("en_US.UTF_8", try canonicalizeLocale(&buf, "en_US.UTF-8")); } + +test "_ returns msgid at comptime" { + const testing = std.testing; + + const msgid = comptime @"_"("Ghostty"); + try testing.expectEqualStrings("Ghostty", std.mem.span(msgid)); +}