2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2

56.2. 面向程式設計師 #

56.2.1. 機制 #

本節介紹如何在 PostgreSQL 發行版的一部分程式或庫中實現本地語言支援。目前,它僅適用於 C 程式。

為程式新增 NLS 支援

  1. 將此程式碼插入程式的啟動序列中

    #ifdef ENABLE_NLS
    #include <locale.h>
    #endif
    
    ...
    
    #ifdef ENABLE_NLS
    setlocale(LC_ALL, "");
    bindtextdomain("progname", LOCALEDIR);
    textdomain("progname");
    #endif
    

    (progname 實際上可以自由選擇。)

  2. 在找到任何可能需要翻譯的訊息的地方,都需要插入對 gettext() 的呼叫。例如:

    fprintf(stderr, "panic level %d\n", lvl);
    

    將改為

    fprintf(stderr, gettext("panic level %d\n"), lvl);
    

    (如果未配置 NLS 支援,則 gettext 定義為無操作。)

    這會增加很多雜亂的程式碼。一個常見的捷徑是使用

    #define _(x) gettext(x)
    

    如果程式透過一個或幾個函式進行大量通訊,例如後端中的 ereport(),則另一種解決方案是可行的。然後,您可以在內部對所有輸入字串呼叫 gettext

  3. 在包含程式原始碼的目錄中新增一個名為 nls.mk 的檔案。此檔案將作為 makefile 讀取。此處需要進行以下變數賦值:

    CATALOG_NAME

    程式名,如 textdomain() 呼叫中所提供。

    GETTEXT_FILES

    包含可翻譯字串的檔案列表,即那些用 gettext 或其他解決方案標記的檔案。最終,這將包括幾乎所有程式原始碼檔案。如果此列表太長,您可以將第一個“檔案”設為 +,第二個詞是一個包含每行一個檔名的檔案。

    GETTEXT_TRIGGERS

    為翻譯人員生成訊息目錄的工具需要知道哪些函式呼叫包含可翻譯的字串。預設情況下,只知道 gettext() 呼叫。如果您使用了 _ 或其他識別符號,則需要在此處列出它們。如果可翻譯字串不是第一個引數,則該項應採用 func:2 的形式(表示第二個引數)。如果您有一個支援複數形式訊息的函式,該項應為 func:1,2(標識單數和複數訊息引數)。

  4. 新增一個名為 po/LINGUAS 的檔案,其中包含提供的翻譯列表 — 最初為空。

構建系統將自動負責構建和安裝訊息目錄。

56.2.2. 訊息編寫指南 #

以下是編寫易於翻譯的訊息的一些指南。

  • 不要在執行時構建句子,例如:

    printf("Files were %s.\n", flag ? "copied" : "removed");
    

    句子內的單詞順序在其他語言中可能不同。此外,即使您記得為每個片段呼叫 gettext(),這些片段可能也無法單獨很好地翻譯。最好複製少量程式碼,以便每個要翻譯的訊息都是一個連貫的整體。只有數字、檔名等執行時變數應該在執行時插入到訊息文字中。

  • 出於類似的原因,這不起作用

    printf("copied %d file%s", n, n!=1 ? "s" : "");
    

    因為它假設了複數是如何形成的。如果您認為可以這樣解決:

    if (n==1)
        printf("copied 1 file");
    else
        printf("copied %d files", n):
    

    那麼您將失望。有些語言有超過兩種形式,並且有一些特殊的規則。通常最好透過避免問題來設計訊息,例如:

    printf("number of copied files: %d", n);
    

    如果您確實想構造一個正確的複數訊息,則支援這樣做,但這有點麻煩。在 ereport() 中生成主要或詳細錯誤訊息時,您可以這樣寫:

    errmsg_plural("copied %d file",
                  "copied %d files",
                  n,
                  n)
    

    第一個引數是適用於英語單數形式的格式字串,第二個是適用於英語複數形式的格式字串,第三個是整數控制值,它決定使用哪種複數形式。後續引數按慣例根據格式字串進行格式化。(通常,複數控制值也將是需要格式化的值之一,因此它必須寫兩次。)在英語中,只有 n 是否等於 1 才重要,但在其他語言中可能有許多不同的複數形式。翻譯者將兩個英語形式視為一個組,並有機會提供多個替換字串,其中一個將根據 n 的執行時值進行選擇。

    如果您需要為不直接傳送到 errmsgerrdetail 報告的訊息新增複數形式,您必須使用底層函式 ngettext。請參閱 gettext 文件。

  • 如果您想與翻譯人員溝通某些資訊,例如關於訊息如何與其他輸出對齊,請在字串出現之前加上一個以 translator 開頭的註釋,例如:

    /* translator: This message is not what it seems to be. */
    

    這些註釋會被複制到訊息目錄檔案中,以便翻譯人員可以看到它們。

提交更正

如果您在文件中發現任何不正確、與您對特定功能的經驗不符或需要進一步說明的內容,請使用 此表單 報告文件問題。