「Tolgee」自行架設(self-hosted),使用docker

上一篇文章「Tolgee」協助您開發多語系APP我建議公司內部使用tolgee;本篇簡易tolgee教學「tolgee該如何使用docker自行架設」

  1. 前置作業要把docker或podman,可以看這篇RockyLinux 安裝 docker準備好。
  2. 準備好外部的資料庫容器(postgres、mariadb),postgress可參考這篇postgres 指令(連線、安裝)
  3. 安裝容器
    這裡我採用連結外部postgres,請先行建立資料庫tolgee,
    其他環境變數(標示紅字),需自行調整。

docker-compose.yaml檔案

version: '3'

services:
app:
image: tolgee/tolgee:latest
volumes:
- ./data:/data
- ./config.yaml:/config.yaml
ports:
- '8090:8080'
deploy:
restart_policy:
condition: on-failure
env_file:
- .env
#若不使用外部postgres,可自架內部專用postgres
# db:
# image: postgres:13
# environment:
# POSTGRES_DB: tolgee
# POSTGRES_USER: admin
# POSTGRES_PASSWORD: admin
# volumes:
# - ./data/postgres:/var/lib/postgresql/data
# ports:
# - '5432ˊ:5432' # 讓外面也可存取

.config.yaml檔案

tolgee:
postgres-autostart:
enabled: false
spring:
datasource:
url: jdbc:postgresql://外部postgreIP:5432/tolgee
username: 帳號
password: 密碼

.env檔案

spring.config.additional-location: file:///config.yaml
TOLGEE_AUTHENTICATION_ENABLED=true
TOLGEE_AUTHENTICATION_INITIAL_PASSWORD=admin
TOLGEE_AUTHENTICATION_INITIAL_USERNAME=admin
TOLGEE_AUTHENTICATION_JWT_SECRET=my_jwt_secret #長度必須大於64
#TOLGEE_MACHINE_TRANSLATION_GOOGLE_API_KEY=my_google_api_key
TOLGEE_SMTP_AUTH=true
TOLGEE_SMTP_FROM=Tolgee <no-reply@mydomain.com>
TOLGEE_SMTP_HOST=email-smtp.regional-region.amazonaws.com
TOLGEE_SMTP_PASSWORD=omg/my/password
TOLGEE_SMTP_PORT=465
TOLGEE_SMTP_SSL_ENABLED=true
TOLGEE_SMTP_USERNAME=user@company.com

# 停用自行註冊功能,只能管理者邀請
TOLGEE_AUTHENTICATION_REGISTRATIONS_ALLOWED=false

# 搞定反向代理之後,請設定網站名稱(不然邀請函只會出現ip)
TOLGEE_FRONT_END_URL=https://tolgee.test.com

安裝完畢,管理者就可以寄發邀請email,或是連結給使用者,讓使用者加入專案

心得結論

Tolgee自架版本雖說有些限制,但已經很好用了,一般小公司有開發app的人已經不得了,不需要用企業版複雜功能。

「Tolgee」協助您開發多語系APP

「Tolgee」是一款新興的翻譯輔助系統,可以協助您開發多語系APP。

目前最有名的雲端翻譯網站為 crowdin,功能強大的付費系統,很推薦使用;若公司需要自行架設(self-hosted),可以參考weblatetolgee,這兩樣都是較有名的免費開源翻譯系統。

以下是 WeblateTolgee 的比較表,以幫助你選擇適合的翻譯與本地化平台:

特性WeblateTolgee
類型自託管 + 雲端自託管 + 雲端
開源✅(完全開源)✅(開源,但部分功能需付費)
托管方式自託管 / Weblate 服務自託管 / Tolgee Cloud
即時協作
支援的格式40+ 種格式(JSON、YAML、PO、XLIFF、TS、ResX 等)JSON、XLIFF、PO、YAML、TS、Java Properties 等
機器翻譯支援 Google、DeepL、Azure、Apertium支援 Google、DeepL、Azure
翻譯記憶庫(TM)
自動提議翻譯
語言品質檢查✅(內建 QA 機制)✅(內建錯誤檢查)
上下文支援🟡(需手動提供)✅(可透過 Tolgee SDK 自動擷取)
API & SDKREST API,可與 Git、CI/CD 整合REST API,專有 SDK(適用於 React、Vue、Angular 等)
Git 整合✅(自動同步)✅(自動同步)
視覺化翻譯(In-context)🟡(有限支援)✅(內建即時預覽)
權限管理✅(細緻的角色與權限控制)✅(細緻的角色與權限控制)
價格免費(自託管)/ 付費雲端免費(基本功能)/ 進階功能需付費
適合對象開發團隊、開源專案、企業需要即時翻譯預覽的開發團隊

實作總結(推薦使用tolgee)

  • Weblate 需先選定APP翻譯格式,然後再進行翻譯,這樣可以直接與APP版控整合,但跨平台APP需要重複翻譯多次(多個格式),另外weblate本身語言翻譯很差(乾脆不要提供各國語系版),寧願使用英文版。
  • Tolgee 則採先翻譯方式,然後再整合不同APP開發格式輸出,這樣只要翻譯一次即可,再匯出讓工程師使用,但無法整合git較不方便。

ps. 到本日(2025/3/22) weblate尚未支援apple string catalog翻譯檔案(.xcstrings),很不方便;而tolgee 3/5之後支援了。

Android開發關於AlertDialog兩三事

開發android都知道,要顯示視窗訊息,不是那直覺方便的,需要搭配Handler參與才能走得順。

# 原本以為myAlterDialog.show()後,就可以馬上執行其他程式商業邏輯,完成後停掉myAlterDialog即可
# (例如我們要實現APP「顯示"請稍後",然後背景執行其他程式商業邏輯,執行完取消"請稍後"」)
# 但我沒想到程式商業邏輯需要寫在Handler裡面才不會讓卡住。

public class MainActivity extends AppCompatActivity {
  AlertDialog.Builder waitBuilder = null;
  AlertDialog waitDialog;
  ...
  protected void onCreate(Bundle savedInstanceState) {
     ...
     waitBuilder = new AlertDialog.Builder(activity);
     waitBuilder.setCancelable(false);
     waitBuilder.setView(R.layout.loading_dialog);
     myAlterDialog = waitBuilder.create();
  }

  public void onStart() {

    adapter.setOnItemLongClickListener(.....){
      ...
      runOnUiThread(new Runnable() {
        @Override
	public void run() {
          myAlterDialog.show();
	  new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
	    @Override
 	    public void run() {
              runOnUiThread(new Runnable() {
                @Override
                public void run() {
                  ...
                  Toast.makeText(activity,"success"....
                  myAlterDialog.dismiss();
                }
              });
	    }
	  }, 300);	
        }
      }
      ...
     });		
   });
}

GIT 版本控管,Client/Server 應該要不分彼(THRIES)此(OURS)才對

一般來說做事不要分彼此,若出現文件衝突,就只好看誰是老大,就聽誰的

Checkout

git checkout --theirs src/.
git checkout --ours src/.

Merge 也很精采,有所謂的合併策略strategy,先記錄下來有這回事,https://git-scm.com/docs/merge-strategies,以後再研究


			
		

Android 13真真氣死人,APP欲取得外部檔案真實路徑有夠困難

後來我才知道 Android 10 (API Level 29) 已經預告取得外部檔案真實路徑的方式已經改

好險,有神人寫了好用的程式能「取得檔案的絕對路徑」,並且在 stackoverflow 說明原由,使用方式也超級方便的,請參找此神人的程式 https://github.com/HBiSoft/PickiT,一定不會失望而歸的。

讓老電腦順順跑win10_win11

我有一台13年前的pentium老電腦4GB ram,安裝windows 10、windows 11都覺得好慢好慢,偶然間看到「雲爸的私處」寫的一篇文章「低端電腦救星 ReviOS Windows 11精簡版系統」,文章推薦的「Revision」是開源軟體。該軟體以前會提供整個windows iso檔,讓人下載後直接安裝;後來改成「腳本」方式,我們只要正常安裝windows,再執行AME Wizard優化程式,載入Revision的腳本,就可以讓舊電腦優化了。

  1. 安裝windows相關元件
    VisualCppRedist_AIO_x86_x64
  2. 執行windows優化軟體
    AME Wizard
  3. 透過AME Wizard執行Revi優化腳本
    AME Wizard執行後,需要載入Revi提供的優化腳本,副檔名為apbx
    Revi優化腳本
  4. 首先腳本會要求關閉windows預設的防禦防毒機制,接下來一直下一步,都用預設值,最後重新開機,就大功告成了

    系統預設會停用更新,可透過桌面上的RevisionTool工具改成可更新


Let’s Encrypt 的 DNS-01 Challenge

自從我懂事以來,都是利用 certbot 進行 「HTTP-01 Challenge」,讓發證單位透過http方式驗證,以取得免費的https證書。

除非遇到Let’sEncrypt考驗伺服器秀逗,否則不可能出問題;長大後,我雄心壯志到各地歷練,發現有些主機 80、443 port 居然被封鎖,沒有了80 port (http),就無法透過HTTP-01考驗方式取得https證書。直到此時,我才知道「代誌不是我們憨人想的架甘丹」—事情不是我們想像的這麼簡單啊。

Let’s Encrypt的Challenge Types,列出支援的驗證類型,裡面提到若 HTTP-01 不能用,還有其他選擇,例如本文要說的:DNS-01 Challenge

DNS-01 使用原理很簡單:DNS伺服器提供ACME DNS API,讓Let’s Encrypt能夠透過API進行考驗,就能取得https證書了。


2024-4-2
新作法 使用開源acme.sh專案

1. 線上安裝

# 若需要使用dns-01方式,email必須是提供API token相同帳號
curl https://get.acme.sh | sh -s email=xxx@test.com
# 安裝完畢程式會在 /root/.acme.sh/acme.sh ("root"因帳號而異)

2. 使用DNS方式授權
取得API Token 或 API Key (以 cloudflare 為例子)

3. 取得授權檔案

/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt

export CF_Key = "b0e689102efab2cf7a1547aaa8b57c4eb65ff"
export CF_Email = "提供API Key之email帳號"
/root/.acme.sh/acme.sh --issue --dns dns_cf -d remote.test.com


export CF_Token = "ibrxxFFlKZ5FrsBpisXRU7GzO_2KzSwRAQoAwbsT"
export CF_Email = "提供API Token之email帳號"
/root/.acme.sh/acme.sh --issue --dns dns_cf -d remote.test.com

# 因為我使用apache httpd、CentOS 7.9;httpd 最高到2.4.6,只能支援RAS加密,不支援ECC;
# 然而acme預設產生的是ECC加密檔案,所以指令需額外加上 -k 4096改成產生RSA加密檔案。
/root/.acme.sh/acme.sh --issue --dns dns_cf -k 4096 -d remote.test.com
# 產生完授權證書後,進行安裝到letsencrypt所在目錄
/root/.acme.sh/acme.sh --install-cert -d remote.test.com \
--cert-file /etc/letsencrypt/live/remote.test.com/cert.pem \
--key-file /etc/letsencrypt/live/remote.test.com/privkey.pem \
--fullchain-file /etc/letsencrypt/live/remote.test.com/fullchain.pem
#自動更新授權證書(會自動加到crontab)
/root/.acme.sh/acme.sh --upgrade --auto-upgrade
# acme產生檔案與 Let's encrypt檔案對應如下
ACME <-> Let's Encrypt
==========================================================
ca.cer <-> cer.pem
fullchain.cer <-> fullchain.pem
remote.test.com.cer <-> chain.pem
remote.test.com.key <-> privkey.pem
==========================================================

(已失效)google domains 為範例:(很可惜google賣掉網域代管業務)

1、先建立權杖(token)

登入google domain後,點選「安全性」->ACME DNS API 「建立權杖」

此權杖只會出現一次,因此複製後,要妥善保存

2、我想使用certbot方式取得憑證,所以到 「certbot-dns-google-domains 」github ,取得執行方式。
2.1 新增權杖檔案

vi /var/lib/letsencrypt/dns_google_domains_credentials.ini
dns_google_domains_access_token = QWVpQWZjT1xxxxxxg2N3lrMi1LUQ==
dns_google_domains_zone = test.com

2.2 docker方式執行,輕鬆取得https證書。

docker run \
  -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
  -v '/etc/letsencrypt:/etc/letsencrypt' \
  --cap-drop=all \
  ghcr.io/aaomidi/certbot-dns-google-domains:latest \
  certbot certonly \
  --authenticator 'dns-google-domains' \
  --dns-google-domains-credentials '/var/lib/letsencrypt/dns_google_domains_credentials.ini' \
  --server 'https://acme-v02.api.letsencrypt.org/directory' \
  --non-interactive \
  --dns-google-domains-zone 'test.com' \
  -d 'xxx.test.com'

3、還有其他取得證書方式(一樣是google domain)
請參考 List of known ACME clients to work the ACME DNS API


若使用的是阿里雲解析,可參考這篇文章,我自己測試結果沒問題;提醒一下,要使用let’s encrypt,dns需要有CAA record 允許let’s encrypt 發證,否則會出現 「Verify error : CAA ……」錯誤

未免忘記,節錄一些指令;
除了指令外,還需要在阿里雲加上RAM帳號,授權該帳號能透過阿里雲OpenAPI修改DNS,
並且取得該RAM帳號「Key」與「Secret」,以下指令需要用到。

yum install socat
curl https://get.acme.sh | sh
vim /root/.acme.sh/acme.sh.env
export LE_WORKING_DIR="/root/.acme.sh"
alias acme.sh="/root/.acme.sh/acme.sh"
export Ali_Key="xxxx"
export Ali_Secret="yyyy"
source ~/.bashrc
env
acme.sh --set-default-ca --server letsencrypt

acme.sh --issue --dns dns_ali --dnssleep 180 -d xxxx.test.com
#若以上指令不行,可改以下指令
acme.sh -f --use-wget --issue --dns dns_ali --dnssleep 180 -d xxxx.test.com

2023/6/16 我在RockyLinux 9.2安裝失敗出現以下問題(google代管之網域)

[Errno 13] Permission denied: '/etc/letsencrypt/.certbot.lock'

這很複雜,原因很多,我的解法如下:

解法1. selinux 放行,然後再關起門來
 setenforce 0 ; docker run \
  -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
  -v '/etc/letsencrypt:/etc/letsencrypt' \
  --cap-drop=all \
  ghcr.io/aaomidi/certbot-dns-google-domains:latest \
  certbot certonly \
  --authenticator 'dns-google-domains' \
  --dns-google-domains-credentials '/var/lib/letsencrypt/dns_google_domains_credentials.ini' \
  --server 'https://acme-v02.api.letsencrypt.org/directory' \
  --non-interactive \
  --dns-google-domains-zone 'test.com' \
  -d 'xxx.test.com' ; setenforce 1;

解法2. 確認相關套件是否安裝
dnf install httpd mod_ssl
certbot --apache
#若出現The requested apache plugin does not appear to be installed,則代表缺少套件
yum list installed|grep certbot
certbot.noarch                                   2.6.0-1.el9                         @epel
python3-certbot.noarch                           2.6.0-1.el9                         @epel
這樣還缺少  python3-certbot-apache , 我再安裝一下
dnf install python3-certbot-apache