Le0
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    ## 以大型語言模型(LLM) 加強開源軟體的在地化翻譯 ─ 以 QGIS 為例 開源軟體的在地化(localization, l10n),從來不只是把英文翻成中文這麼簡單。 對使用者而言,介面用語是否一致、訊息是否清楚、快捷鍵是否正常運作,會直接影響學習成本與操作信心;對維護者而言,翻譯能否追蹤、延續與交接,則決定了專案能否長期維護,而不是仰賴少數人的經驗撐場。 以 QGIS 為例,其繁體中文翻譯主要透過 Qt 的 `.ts` 檔案進行管理。這類檔案除了自然語言文字,還包含與介面行為緊密綁定的功能性元素,例如:快捷鍵(`&File`、`E&xit`)、參數佔位符(`%1`、`%n`、`{0}`)、HTML 標籤,以及複數型結構(`numerus` / `<numerusform>`)。這些內容在視覺上像一般文字,但實際上會影響 UI 顯示與互動;一旦在翻譯過程中被誤改或遺漏,就可能造成介面行為異常或訊息顯示錯誤。 ## 從加速翻譯,到放大風險? 近年大型語言模型(Large Language Model, LLM)逐漸被引入在地化流程。LLM 能快速產出大量初稿,對人力有限的開源社群確實很有吸引力;但在「專業語境 + 嚴格格式約束」的情境下,LLM 的改寫式生成也會把風險往格式層面推高。 更麻煩的是,這類錯誤往往不容易用「讀起來順不順」發現:即使語意看似合理,只要佔位符(placeholder,如:`%n`)、快捷鍵或複數結構被動到,就可能直接影響功能。於是審稿工作的重心也會從術語與語意,轉向大量的格式比對、結構驗證與修補。 因此,引入 LLM 的重點不該只放在「加速產出」,而應把它當成流程中的一個步驟:在輸入端先定義規則,在輸出端建立檢查機制,才能把風險控制在可維護的範圍內。 ## QGIS 在地化的典型痛點 回到實務上,QGIS 的繁體中文在地化長期面臨幾個挑戰。 第一是術語與風格一致性。字串分散於不同模組與外掛程式,若缺乏穩定的術語表與檢核流程,同一概念容易出現多種譯法,增加使用者理解成本,也提高維護者的溝通與審核負擔。 為降低同義多譯,流程可匯入 glossary(CSV/ODS)作為約束。系統會在翻譯時把「命中的術語對照」一併提供給 LLM,讓輸出更容易收斂到一致用語。 其次是在多人協作與跨版本沿用的情況下,介面字串常出現中英夾雜、繁簡混用,甚至同一功能在不同頁面使用不同寫法(如:同時存在「圖層 / Layer」、「欄位 / 字段」、「設定 / 設置」等)。這不只影響閱讀一致性,也會讓使用者對系統用語產生不確定感,進一步提高學習成本。 最後則是 `.ts` 格式的脆弱性。它同時承載文字與功能標記,任何跨版本沿用、多人協作,或導入非 i18n(internationalization)導向的工具(如:一般文字編輯器、AI 改寫/翻譯工具、缺乏占位符與 XML 規則檢查的流程),都可能放大「不小心動到格式」的機率;而 LLM 若沒有明確規則與自動檢查,這類問題只會更容易發生。 ## 此專案目標 1. **翻譯可直接使用** 維持跨模組術語一致,並確保快捷鍵、占位符與複數形式等結構元素不被變更。 2. **維護流程可交接** 透過流程與工具設計,使翻譯、審核與修正能被重複執行與追蹤,降低對少數人經驗的依賴。 3. **方法可移植與擴散** 將術語庫與檢核規則模組化,便於套用到其他 Qt / `.ts` 專案與不同領域的翻譯情境。 4. **LLM 輸出可控且可驗證** 結合格式檢查與多階段處理策略,提高輸出穩定性,降低人工校對與修正負擔。 ## 在地化翻譯處理流程 此方法並不將 LLM 視為單純的翻譯工具,而是將其納入一套流程導向的開源軟體在地化方法中。 其核心設計在於,透過分段式翻譯處理與多層檢查機制,將原本常於翻譯完成後或寫回 `.ts` 檔階段才被發現的風險(如:術語不一致、占位符錯誤與格式破壞),前移至翻譯生成與初步篩選階段即加以辨識與排除。 同時,藉由多次生成與規則篩選,使翻譯結果逐步收斂至一組在語義、術語與格式上皆符合在地化需求的候選結果,從而提升流程的可重複性、可追蹤性與跨人員交接能力。 ![圖 1:流程圖](https://hackmd.io/_uploads/SJSLqHWBWx.png) >圖 1:在地化翻譯處理流程圖 在此流程設計中,六個階段皆可由系統自動執行,過程中不需人工即時介入。 人工僅於流程完成並產出 `.ts` 檔案後,依專案需求進行最終審閱、與原始翻譯檔合併,或直接提交至版本控制系統作為開源貢獻,從而在維持自動化流程一致性的同時,保留人工審查的彈性。 ### Step 1:界定翻譯範圍與工作量 首先是釐清本次工作的範圍。 系統會解析上傳的 `.ts` 檔案,計算實際可翻譯的 `<source>` 句數,並將其視為本次處理的明確範圍,使進度與成本在一開始即可被掌握。 若同時提供舊版 `.ts`,流程會優先比對 `<source>` 是否完全一致,能沿用的翻譯直接套用,不再進入後續翻譯流程,以避免不必要的重複處理。 ### Step 2:翻譯前標記功能性格式片段 在送入模型之前,會先掃描每筆字串,標記其中所有與介面行為相關的格式元素,例如: - 參數佔位符(`%1`、`%n`、`{0}`) - HTML 標籤結構(`<html>`) - 快捷鍵標記(`&`) - 複數型結構(`numerus` / `<numerusform>`) 這些標記會被保留下來,作為後續檢查與修補的比對基準,讓「格式是否被破壞」成為可被判斷的條件,而非完全依賴人工檢視。 同樣地,glossary 也會在翻譯前先做搜尋:對 `<source>` 與字詞做標準化後,以子字串/LCS 類相似度做近似比對,避免複數或符號差異漏抓。命中的字詞會整理成「建議/指定譯法」提示,跟原文一起送進 LLM。 ### Step 3:多次生成翻譯候選以降低偶發錯誤 在翻譯產生階段,同一筆 `<source>` 不只產生單一結果,而是由模型多次生成翻譯候選。 目的並非追求文風多樣,而是降低單次生成的偶發錯誤(如: 術語不一致、結構破壞)對整體流程的影響,提高取得「語意合理且格式可寫回」結果的機率。 ### Step 4:以規則初篩,排除明顯不可用輸出 在進入修補或校正前,會依 Step 2 的標記規則對翻譯候選進行初篩,先排除明顯不可用的結果(如: 占位符缺失、結構破壞或複數結構不完整),避免錯誤被帶入後續流程。 ### Step 5:將「格式修補」與「重新翻譯」明確分離 對於仍存在格式問題但語意合理的翻譯,不會直接重翻,而是將「格式修補」視為獨立任務。 此階段以「最小變更」為原則:在語意盡量不變的前提下修正格式,避免第二階段造成術語與用語再次不一致。 ### Step 6:寫回前的最終驗證 在結果寫回 `.ts` 檔案之前,會進行最後一道驗證:確認輸出與 Step 2 的格式標記一致,且整體 XML 結構合法可解析。 若未通過驗證,將依錯誤類型回退處理:需要補齊或修正格式者回到 Step 5,需要重新生成候選者回到 Step 3;避免產出可能影響介面行為的檔案。 ## 使用工具 工具連結:[使用 ChatGPT API 進行翻譯](https://wendy062644.github.io/2025-summer-intern-project-2/pages/app_api.html) ### 主要功能 + **API 與模型設定**: + 支援填入 API Key 與 Base URL + 可選擇主要翻譯模型(Model-1) + 可於介面編輯 Prompt:每次執行時以介面內容為準;若留空則使用預設內容 + **兩階段翻譯(可選)**: + 使用 Model-1 進行初步翻譯 + 啟用 Model-2 進行版本挑選與格式校正,以提升翻譯穩定度 + **批次處理與筆數控制**: + 支援 Batch 翻譯模式 + 可設定處理筆數上限,先進行小量測試再擴大執行 + **沿用舊版 `.ts`**: + 當 `<source>` 內容相同時,直接套用舊版翻譯 + 以降低不必要的 API 呼叫次數 + **glossary 詞彙表**: + 支援 CSV/ODS 格式詞彙表 + 用於確保專有名詞與術語的一致性 + **執行 / 暫停 + 即時對照**: + 支援翻譯流程的執行與暫停 + 可即時檢視原文與譯文的對照結果 ![image](https://hackmd.io/_uploads/HJKBwA7Ubx.png) > 圖2:`.ts` 檔線上翻譯工具介面 ## 結果 > 表1:以 QGIS 3.40 為例 | 原預設繁體中文 | 重新翻譯並修正後 | | --- | --- | | ![](https://hackmd.io/_uploads/B1Y3mlGH-e.png) | ![](https://hackmd.io/_uploads/Bkw3XezHZx.png) | --- 在本專題開始前,QGIS 繁體中文翻譯於 Transifex 上之完成度約為 70%。 經由本文流程補齊未翻譯字串,並修正既有翻譯中的簡體中文、英文與錯誤內容後,整體翻譯完成度已提升至 99%。 ![image](https://hackmd.io/_uploads/S1LXIJAU-x.png) > 圖3:透過 Transifex 將翻譯後的 `.ts` 檔貢獻回 QGIS Depositar 資料集:https://data.depositar.io/dataset/qgis_zh-hant

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully