GNU gettext 快速上手

文章目錄

  • 1.簡介
  • 2.核心概念
    • 國際化 (i18n)
    • 本地化 (l10n)
    • POT 文件
    • PO 文件
    • MO 文件
    • 文本域
    • 翻譯函數
  • 3.主要組件
  • 4.使用示例
  • 參考文獻

1.簡介

GNU gettext 是一套用于軟件國際化(internationalization,i18n)和本地化(localization,l10n)的工具集,它幫助開發者創建多語言應用程序。

下面大致翻譯自 GetText 主頁的介紹 :

“通常,程序及其文檔信息都是用英語語言寫的,程序運行時同用戶交 互的信息也是英語。這是一個事實,不僅僅 GNU 的軟件是這樣,其他大 部分私有軟件或自由軟件也是這樣。一方面,對于來自所有國家的開 發者、維護者和用戶來說,相互溝通中使用一種通用的語言非常的方便。另一方面,相對于母語來說大多數人并不適應使用英語,而且他 們的日常工作都是盡可能的使用他們自己的母語。多數人都會喜歡他 們的計算機屏幕顯示的英語更少,顯示的母語更多。"


GNU 的 ‘gettext’ 是 GNU 翻譯項目的一個重要步驟,我們依賴于它 來作很多其他的步驟。該軟件包為程序員、翻譯人員甚至用戶提供了一套集成良好的工具和文檔。詳細地說,GNU gettext 提供了一套工具, 能讓其他 GNU 軟件創建多語言信息。這些工具包括一組關于如何編寫程序以支持消息目錄的約定,消息目錄本身的目錄和文件命名組織,支持檢索已翻譯消息的運行時庫,以及一些以各種方式處理可翻譯字符串集或已翻譯字符串集的獨立程序。一個特殊的 GNU Emacs 模式也可以幫助有興趣的各方準備這些集合,或者使它們更新。

gettext 的工作流程是這樣的:比如我們寫一個 C 程序,通常 printf 等輸 出信息都是 English 的。如果我們在程序中加入 gettext 支持,在需要交互的字符串上用 gettext 函數,程序運行就可以先調用 gettext 函數處理字符串,替換當前的字符串。注意是運行時替換

2.核心概念

國際化 (i18n)

國際化(Internationalization)簡寫為 i18n,其中 i 和 n 分別代表單詞的第一個和最后一個字母,中間的"18"代表省略的18個字母。

國際化是設計和開發軟件應用的過程,使其架構能夠支持多種語言和地區設置,而無需進行重大修改。

國際化的關鍵任務包括:

  • 將所有用戶界面元素(如文本、圖標)從代碼中分離出來,使其可以獨立于代碼進行更改。
  • 使用通用的日期、時間和數字格式,可以根據用戶的地區設置進行調整。
  • 支持多種字符編碼,如 UTF-8,確保可以處理各種語言的輸入和顯示。
  • 設計靈活的布局,可以適應從右到左的閱讀順序等不同的文本方向。

本地化 (l10n)

本地化(Localization)簡寫為 l10n,其中 l 和 n 分別代表單詞的第一個和最后一個字母,中間的"10"代表省略的10個字母。

本地化是將國際化的軟件適配到特定地區或語言的過程,涉及翻譯文本和調整功能以符合特定文化和語言的需求。

本地化的關鍵任務包括:

  • 翻譯軟件界面、幫助文檔以及其他用戶面向的文本。
  • 調整圖形元素,使其符合地區文化的期望和標準。
  • 根據目標市場的習慣和法律要求調整軟件功能,如貨幣、稅率計算等。
  • 適應地區特有的日期、時間、地址和電話號碼格式。

POT 文件

POT 文件(Portable Object Template)是 GNU gettext 工具鏈中的翻譯模板文件,用于軟件國際化和本地化(i18n/l10n)。

它作為翻譯模板,存儲源代碼中提取的原始字符串(通常是英文),供后續生成多語言 PO(Portable Object)文件使用。

文件頭:元數據(如語言、字符集、復數形式規則等)

msgid ""
msgstr ""
"Project-Id-Version: MyApp 1.0\n"     # 項目名稱和版本
"POT-Creation-Date: 2025-04-28 12:00\n"  # 創建時間
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"  # PO文件修訂時間(模板中通常留空)
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"  # 最后譯者(PO文件填充)
"Language-Team: LANGUAGE <LL@li.org>\n"       # 翻譯團隊(PO文件填充)
"Language: \n"                         # 語言代碼(PO文件填充,POT中為空)
"MIME-Version: 1.0\n"                  # MIME版本
"Content-Type: text/plain; charset=UTF-8\n"  # 字符集(通常UTF-8)
"Content-Transfer-Encoding: 8bit\n"    # 編碼方式
"Plural-Forms: nplurals=2; plural=(n != 1);\n"  # 復數規則(示例為英語)

不同語言的復數形式不同(如俄語有3種復數形式,阿拉伯語有6種),需根據語言調整 nplurals 和 plural 表達式。

PO 文件

PO(Portable Object)特定語言的翻譯文件,基于 POT 文件生成,由翻譯人員填充具體語言的譯文。

示例:

msgid "Hello, world!"
msgstr "你好,世界!"

MO 文件

MO(Machine Object)文件,PO 文件的二進制編譯版本,供程序運行時高效加載。

特點:

  • 二進制格式,不可直接編輯。
  • 文件擴展名:.mo。
  • 由 msgfmt 工具從 PO 文件編譯生成。
  • 程序通過 gettext() 函數讀取 MO 文件中的翻譯。

文本域

文本域(Text Domain)是 gettext 中用來管理和隔離翻譯資源的一個重要機制。

文本域允許程序將其翻譯文件組織在不同的命名空間內,使同一程序可以同時加載多個獨立的翻譯文件(MO 文件)。

在代碼中通過 textdomain() 函數設置當前文本域:

#include <libintl.h>
textdomain("myapp");  // 設置文本域為 "myapp"

在翻譯文件中,MO 文件需放在特定路徑:

./locale/<語言>/LC_MESSAGES/<文本域>.mo# 例如
./locale/zh_CN/LC_MESSAGES/myapp.mo

若程序需要同時使用多個文本域(如主程序和插件):

// 臨時切換文本域(保存舊域)
char* old_domain = textdomain("plugin1");
printf("%s", gettext("Delete"));  // 使用 plugin1 的翻譯
textdomain(old_domain);           // 恢復原文本域

注意,MO 文件必須與文本域同名:

文本域 "myapp"  -> MO 文件名為 myapp.mo
文本域 "gtk" -> MO 文件名為 gtk.mo

標準存放路徑:

/usr/share/locale/zh_CN/LC_MESSAGES/myapp.mo  # 系統級
./locale/zh_CN/LC_MESSAGES/myapp.mo           # 項目內

翻譯函數

函數作用示例
textdomain()設置/獲取當前文本域textdomain(“myapp”);
bindtextdomain()指定文本域的 MO 文件搜索路徑bindtextdomain(“myapp”, “./locale”);
gettext()根據當前文本域獲取翻譯gettext(“Hello”);
dgettext()顯式指定文本域獲取翻譯dgettext(“plugin1”, “Save”);
ngettext()根據給定的數量(n)選擇正確的單數或復數翻譯字符串ngettext(“%d file”, “%d files”, n);

3.主要組件

  1. 開發庫

libintl:提供 gettext() 等國際化函數

支持多種編程語言:C, C++, Python, Java, Perl, PHP 等。

  1. 工具集

xgettext:從源代碼提取可翻譯字符串,生成 POT 文件(翻譯模板文件)。

msginit:根據 POT 文件創建新的 PO 文件(翻譯文件)。

msgmerge:合并新舊 PO 文件。

msgfmt:將 PO 文件編譯為 MO 文件。

  1. 運行時組件

gettext:在運行時根據當前 locale 加載適當的翻譯。

4.使用示例

下面以 C 語言給出使用示例。

  1. 標記源代碼。
#include <stdio.h>
#include <locale.h>
#include <libintl.h> // gettext 頭文件// 定義簡化宏(約定俗成)
#define _(STRING) gettext(STRING)
#define LOCALEDIR "/usr/share/locale" // 翻譯文件存放目錄int main() {// 1.設置本地化環境采用系統默認設置。// 必須調用,否則 gettext 無法正確加載翻譯。setlocale(LC_ALL, "");// 2.綁定文本域(指定翻譯文件位置和名稱)bindtextdomain("hello", LOCALEDIR);textdomain("hello"); // 設置當前文本域// 3.使用可翻譯字符串printf(_("Hello, World!\n"));printf(_("This is a demo of gettext.\n"));// 4.帶變量的翻譯int count = 3;printf(_("You have %d new message.\n"), count);return 0;
}
  1. 提取字符串。

一旦您具有了使用 gettext 調用的代碼,您可以使用 xgettext 從中提取消息,并將它們存儲在 .pot 中

xgettext -d hello --keyword=_ -o hello.pot main.c

-d hello 指定生成的翻譯模板文件(.pot)關聯的文本域(text domain)為 “hello”。

文本域是 gettext 系統中用于區分不同模塊或應用程序翻譯的命名空間。

--keyword 查找被指定關鍵詞包裹的字符串。

生成的翻譯模板文件內容如下:

cat hello.pot# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-30 18:31+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"#: main.c:18
#, c-format
msgid "Hello, World!\n"
msgstr ""#: main.c:19
#, c-format
msgid "This is a demo of gettext.\n"
msgstr ""#: main.c:23
#, c-format
msgid "You have %d new message.\n"
msgstr ""
  1. 創建翻譯文件。

這里創建中文簡體的翻譯文件 zh_CN.po。

msginit --input=hello.pot --locale=zh_CN -o hello.po

-i, --input 參數指定輸入的模板文件,包含了所有待翻譯的字符串。這個文件通常是通過 xgettext 命令從源代碼中提取所有標記為翻譯的字符串得到的。

-l, --locale參數指定了目標語言的語言代碼,這里使用 zh_CN 表示簡體中文。語言代碼通常由兩部分組成:語言(zh)和國家/地區(CN),這里 CN 代表中國。這個參數告訴 msginit 創建一個針對中文簡體的 .po 文件。

  1. 編輯翻譯文件進行翻譯。
msgid "Hello, World!"
msgstr "你好,世界!"msgid "This is a demo of gettext."
msgstr "這是一個gettext的演示。"msgid "You have %d new message.\n"
msgstr "你有 %d 條新消息。\n"
  1. 編譯翻譯文件。

使用工具 msgfmt 將 PO 文件編譯為程序使用的二進制 MO 文件。

msgfmt -o hello.mo hello.po

如果出現如下錯誤:

zh_CN.po:22:11: invalid multibyte sequence
zh_CN.po:22:16: invalid multibyte sequence
zh_CN.po:22:17: invalid multibyte sequence
...

說明生成的 PO 文件頭中的元信息 Content-Type 不對,需要修改成正確的字符編碼。

# 原來 GB2312
"Content-Type: text/plain; charset=UTF-8\n"# 改成 UTF-8
"Content-Type: text/plain; charset=UTF-8\n"

為什么使用 msginit 生成的 PO 文件字符編碼為 GB2312 呢?

注意: MO 文件必須與文本域同名。

因為代碼中使用的文本域為 hello,所以這里生成的 MO 文件需要命名為 hello.mo。

將生成的 MO 文件拷貝至代碼中使用的文本域目錄:

cp hello.mo /usr/share/locale/zh_CN/LC_MESSAGES/
  1. 驗證多語言是否生效。

編譯上面的示例程序。

gcc main.c -o hello.out

執行 hello.out 輸出如下結果:

LANG=zh_CN.UTF-8 ./hello.out你好,世界!
是一個gettext的演示。
你有 3 條新消息。

注意,執行程序前需要臨時設置環境變量 LANG 為 zh_CN.UTF-8,表明程序的語言環境和字符編碼為簡體中文和 UTF-8,這樣程序就可以去 locale 目錄找到特定語言的文本域對應的翻譯文件(MO 文件),這里是 hello.mo 文件且字符編碼為 UTF-8。這樣程序就可以將 gettext 包裹的內容翻譯成簡體中文了。


參考文獻

deepseek.com
gettext - GNU Project - Free Software Foundation
使用GNU gettext 來翻譯軟件 - Weblate

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/903582.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/903582.shtml
英文地址,請注明出處:http://en.pswp.cn/news/903582.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

分享:VTK版本的選擇 - WPF空域問題

在早期版本中&#xff0c;ActiViz 對 Windows Presentation Foundation (WPF) 框架的支持是通過 WindowsFormHost 組件實現的&#xff0c;這種方式依賴于 WindowsForm 和 WPF 的互操作性。然而&#xff0c;這種方法存在一個眾所周知的“空域問題”&#xff08;airspace issue&a…

python數據分析(六):Pandas 多數據操作全面指南

Pandas 多數據操作全面指南&#xff1a;Merge, Join, Concatenate 與 Compare 1. 引言 在數據分析工作中&#xff0c;我們經常需要處理多個數據集并將它們以各種方式組合起來。Pandas 提供了多種強大的多數據操作方法&#xff0c;包括合并(merge)、連接(join)、連接(concaten…

spring 面試題

一、Spring 基礎概念 什么是 Spring 框架&#xff1f; Spring 是一個開源的 Java 應用程序框架&#xff0c;它提供了一種輕量級的、非侵入式的方式來構建企業級應用。Spring 的核心功能包括依賴注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;、面向切面編程…

OpenCV-Python (官方)中文教程(部分一)_Day20

22.直方圖 22.1直方圖的計算,繪制與分析 使用 OpenCV 或 Numpy 函數計算直方圖 使用 Opencv 或者 Matplotlib 函數繪制直方圖 將要學習的函數有&#xff1a;cv2.calcHist(),np.histogram() 什么是直方圖呢&#xff1f;通過直方圖你可以對整幅圖像的灰度分布有一個整體的 了…

數電發票整理:免費實用工具如何高效解析 XML 發票數據

如今數字電子發票越來越普及&#xff0c;但是數電發票的整理還是頗有講究~ 今天給大家介紹一個 XML 發票閱讀器。使用它完全不收取任何費用&#xff0c;且無廣告干擾&#xff0c;對財務人員而言十分實用。 01 軟件介紹 這款軟件就是XML格式&#xff08;數電票&#xff09;閱讀…

深度學習正則化:原理、方法與應用深度解析

摘要 本文深入探討深度學習中的正則化技術&#xff0c;介紹其避免過擬合的重要性&#xff0c;詳細講解常見的正則化方法&#xff0c;如 L 1 L_1 L1?和 L 2 L_2 L2?正則化、Dropout等&#xff0c;并通過線性回歸案例和神經網絡訓練流程對其進行直觀闡釋。幫助讀者理解正則化原…

【爬蟲】deepseek談爬蟲工具

2025 年&#xff0c;隨著 Web 技術的演進和反爬機制的升級&#xff0c;工具生態也會進一步優化。以下是 2025 年爬蟲 & 自動化測試的前沿工具預測&#xff0c;結合行業趨勢和現有技術發展方向&#xff1a; &#x1f680; 2025 年推薦組合&#xff08;預測版&#xff09; 1…

SQLMesh 測試自動化:提升數據工程效率

在現代數據工程中&#xff0c;確保數據模型的準確性和可靠性至關重要。SQLMesh 提供了一套強大的測試工具&#xff0c;用于驗證數據模型的輸出是否符合預期。本文將深入探討 SQLMesh 的測試功能&#xff0c;包括如何創建測試、支持的數據格式以及如何運行和調試測試。 SQLMesh …

Java學習手冊:Spring 中常用的注解

一、組件注解 Component &#xff1a;用于標記一個類為 Spring 管理的 Bean&#xff0c;是 Spring 的基本組件注解。Spring 會通過類路徑掃描自動檢測并注冊標記了 Component 的類為 Bean。Service &#xff1a;是 Component 的派生注解&#xff0c;用于標記服務層類&#xff…

前端跨域問題詳解:原因、解決方案與最佳實踐

引言 在現代Web開發中&#xff0c;跨域問題是前端工程師幾乎每天都會遇到的挑戰。隨著前后端分離架構的普及和微服務的發展&#xff0c;跨域請求變得愈發常見。本文將深入探討跨域問題的本質、各種解決方案以及在實際開發中的最佳實踐。 一、什么是跨域問題&#xff1f; 1.1…

[計算機網絡]物理層

文章目錄 物理層的概述與功能傳輸介質雙絞線:分類:應用領域: 同軸電纜&#xff1a;分類: 光纖&#xff1a;分類: 無線傳輸介質&#xff1a;無線電波微波&#xff1a;紅外線&#xff1a;激光&#xff1a; 物理層設備中繼器&#xff1a;放大器&#xff1a;集線器(Hub)&#xff1a…

大連理工大學選修課——機器學習筆記(9):線性判別式與邏輯回歸

線性判別式與邏輯回歸 概述 判別式方法 產生式模型需要計算輸入、輸出的聯合概率 需要知道樣本的概率分布&#xff0c;定義似然密度的隱式參數也稱為基于似然的分類 判別式模型直接構造判別式 g i ( x ∣ θ i ) g_i(x|\theta_i) gi?(x∣θi?)&#xff0c;顯式定義判別式…

OpenCV 圖像處理核心技術 (第二部分)

歡迎來到 OpenCV 圖像處理的第二部分&#xff01;在第一部分&#xff0c;我們學習了如何加載、顯示、保存圖像以及訪問像素等基礎知識。現在&#xff0c;我們將深入探索如何利用 OpenCV 提供的強大工具來修改和分析圖像。 圖像處理是計算機視覺領域的基石。通過對圖像進行各種…

【鴻蒙HarmonyOS】一文詳解華為的服務卡片

7.服務卡片 1.什么是卡片 Form Kit&#xff08;卡片開發服務&#xff09;提供一種界面展示形式&#xff0c;可以將應用的重要信息或操作前置到服務卡片&#xff08;以下簡稱“卡片”&#xff09;&#xff0c;以達到服務直達、減少跳轉層級的體驗效果。卡片常用于嵌入到其他應…

探索目標檢測:邊界框與錨框的奧秘

筆者在2022年開始學習目標檢測的時候&#xff0c;對各種框的概念那是相當混淆&#xff0c;比如&#xff1a; 中文名詞&#xff1a;邊界框、錨框、真實框、預測框等英文名詞&#xff1a;BoundingBox、AnchorBox、Ground Truth等 同一個英文名詞比如BoundingBox翻譯成中文也有多個…

[原創](現代Delphi 12指南):[macOS 64bit App開發]: [1]如何使用原生NSAlert消息框 (runModal模式)

[作者] 常用網名: 豬頭三 出生日期: 1981.XX.XX 企鵝交流: 643439947 個人網站: 80x86匯編小站 編程生涯: 2001年~至今[共24年] 職業生涯: 22年 開發語言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 開發工具: Visual Studio、Delphi、XCode、…

LangChain的向量RAG與MCP在意圖識別的主要區別

LangChain的向量RAG與MCP在意圖識別實現上的區別主要體現在技術路徑、流程設計以及應用場景三個方面&#xff1a; 1. 技術路徑差異 LangChain向量RAG 語義相似度驅動&#xff1a;通過用戶輸入的原始查詢與向量化知識庫的語義匹配實現意圖識別。例如&#xff0c;用戶提問"…

[特殊字符] Spring Cloud 微服務配置統一管理:基于 Nacos 的最佳實踐詳解

在微服務架構中&#xff0c;配置文件眾多、管理復雜是常見問題。本文將手把手演示如何將配置集中托管到 Nacos&#xff0c;并在 Spring Cloud Alibaba 項目中實現統一配置管理 自動刷新機制。 一、為什么要使用 Nacos 統一配置&#xff1f; 傳統方式下&#xff0c;每個服務都…

2025平航杯—團隊賽

2025平航杯團隊賽 計算機取證 分析起早王的計算機檢材&#xff0c;起早王的計算機插入過USB序列號是什么(格式&#xff1a;1)分析起早王的計算機檢材&#xff0c;起早王的便簽里有幾條待干(格式&#xff1a;1)分析起早王的計算機檢材&#xff0c;起早王的計算機默認瀏覽器是什…

JSON-RPC 2.0 規范中文版——無狀態輕量級遠程過程調用協議

前言 JSON-RPC是一種簡單、輕量且無狀態的遠程過程調用&#xff08;RPC&#xff09;協議&#xff0c;它允許不同系統通過標準化的數據格式進行通信。自2010年由JSON-RPC工作組發布以來&#xff0c;已成為眾多應用中實現遠程交互的基礎協議之一。本規范主要表達了JSON-RPC 2.0版…