ローカル環境の Mac でいろいろなアプリケーションから PLaMo翻訳を使いたい
はじめに
PLaMo翻訳がなかなか素敵なので、ショートカットや PopClip、AppleScript を利用していろいろなアプリケーションから呼び出せるようにしました。
(2025.12.07 追記)
初公開時のスクリプトに翻訳時に処理が進まないことがあるバグがあったため内容を修正しました。
実際に試されて同じ症状に見舞われた方につきましては、ご迷惑をおかけしまして申しわけございません。
バグの原因と対策につきましては最後に追記しております。
0. 今回の環境
- MacBook Air (Apple M2)
- macOS Tahoe 26.1
- plamo-translate-cli 1.0.5
- PopClip 2025.9.2
PopClip は iOS のポップアップメニューのようなメニューを macOS で実現できるアプリケーションです。
機能拡張で様々な機能を追加できます。
1. plamo-translate-cli をインストール
公式に従って plamo-translate-cli をインストールします。
実行ファイル (plamo-translate) のシンボリックリンクを /usr/local/bin/ に作ります。
ln -s /path/to/plamo-translate /usr/local/bin/.
2. ショートカットを作成
標準モデルでもサーバー起動中はかなりメモリを圧迫するため、サーバーを操作するショートカットを作ります。
plamo-translate コマンドに --precision オプションを付けることでモデルサイズを選択できます [4bit, 8bit, bf16] (デフォルト: 4bit)。
export TMPDIR=/tmp
/usr/local/bin/plamo-translate server >/dev/null 2>&1 &

pkill -f 'plamo-translate'

3. LaunchAgent の設定ファイルを作成 (オプション)
メモリ盛り盛りのリッチマシンをお持ちの方は LaunchAgent を利用してログイン時にサーバーを起動させてもいいかもしれません。
設定用の .plist ファイルを ~/Library/LaunchAgents/ の中に作成します。
ファイル名やソース内の「your.name」は任意の文字列に書き換えてください。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>your.name.plamo-server</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/plamo-translate</string>
<string>server</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>TMPDIR</key>
<string>/tmp</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<false/>
<key>StopOnUnload</key>
<true/>
</dict>
</plist>
4. PopClip 機能拡張を作成
フォルダを作成し、名前の末尾を .popclipext にすることでパッケージにします。
その中に設定用の JSON ファイルと AppleScript を配置します。
.
└─ PlamoTranslate.popclipext
├─ Config.json
└─ translate.applescript
JSON ファイルについても「your.name」を任意の文字列に書き換えてください。
基本項目以外にオプション項目を追加することで翻訳元と翻訳先を選べるようにしました。
{
"name": "PLaMo Translate",
"identifier": "your.name.plamo-translate",
"description": "Translate text using plamo-translate",
"popclip version": 5155,
"icon": "text:PL",
"options": [
{
"label": "Source Language",
"type": "multiple",
"identifier": "source",
"values": ["English|Japanese",
"Japanese",
"Japanese(easy)",
"English",
"Chinese",
"Taiwanese",
"Korean",
"Arabic",
"Italian",
"Indonesian",
"Dutch",
"Spanish",
"Thai",
"German",
"French",
"Vietnamese",
"Russian"]
},
{
"label": "Target Language",
"type": "multiple",
"identifier": "target",
"values": ["English|Japanese",
"Japanese",
"Japanese(easy)",
"English",
"Chinese",
"Taiwanese",
"Korean",
"Arabic",
"Italian",
"Indonesian",
"Dutch",
"Spanish",
"Thai",
"German",
"French",
"Vietnamese",
"Russian"]
}
],
"applescriptFile": "translate.applescript"
}
AppleScript はテキスト形式で保存します。
翻訳時にサーバーが起動していない場合、サーバーを起動してから翻訳コマンドを実行するようにしました。
サーバーは 2. で作成したショートカットを実行して起動させるので、ファイル名を間違えないように気を付けてください。
set source to "{popclip option source}" -- 翻訳元言語
set target to "{popclip option target}" -- 翻訳先言語
set input to "{popclip text}" -- 入力テキスト
set configPath to "/tmp" -- 設定ファイルの保存先
set configFile to configPath & "/plamo-translate-config.json" -- 設定ファイル
set isRunning to false
try -- サーバーが起動しているか確認
do shell script "pgrep -f 'plamo-translate server'"
set isRunning to true
end try
if isRunning is false then -- サーバーが起動していなければ起動
do shell script "shortcuts run 'PLaMo-Translate ON'" -- ファイル名注意
end if
try -- ポート番号取得
set portNumber to do shell script "sed -n 's/.*\"port\": *\\([0-9]*\\).*/\\1/p' " & quoted form of configFile
set portNumber to portNumber as integer
on error errMsg -- ポート番号が取得できなかった場合
display dialog "Error reading config: " & errMsg buttons {"OK"} default button "OK" with icon stop
error number -128
end try
set isReady to false
repeat 30 times -- サーバーの準備が出来ているか確認
try
set httpStatus to do shell script "curl -s -o /dev/null -w '%{http_code}' http://localhost:" & portNumber
if httpStatus is "200" or httpStatus is "404" then
set isReady to true
exit repeat
end if
end try
delay 0.5
end repeat
if isReady is false then -- サーバーが応答しない場合
display dialog "Server not responding on port " & portNumber buttons {"OK"} default button "OK" with icon stop
error number -128
end if
try -- 翻訳実行
set translateResult to do shell script "export TMPDIR=" & quoted form of configPath & "; /usr/local/bin/plamo-translate --from " & quoted form of source & " --to " & quoted form of target & " --input " & quoted form of input
set dialogResult to display dialog translateResult buttons {"Copy", "OK"} default button "OK"
if button returned of dialogResult is "Copy" then -- "Copy" の場合クリップボードにコピー
set the clipboard to translateResult
end if
on error errMsg -- 翻訳コマンドでエラーが発生した場合
display dialog "Translation error: " & errMsg buttons {"OK"} default button "OK" with icon stop
error number -128
end try
5. PopClip 機能拡張のインストール
完成した機能拡張パッケージをダブルクリックします。
署名がないため警告が出ますが、そのままインストールします。

6. 動作テスト
テキストを選択してポップアップメニューが出たら [PL] をクリックします。

翻訳結果がダイアログに表示されれば成功です。
結果をクリップボードにコピーする場合は [Copy] ボタンをクリックしてください。

アクティビティモニタを起動し、PLaMo-Translate ON/OFF でサーバーが起動/停止するか確認してください。

5GB (デフォルトモデルの場合) の python プロセスが PLaMo翻訳サーバー
7. サービスメニューや共有シートからも翻訳できるようにする
新規に AppleScript を実行するショートカットを作成します。
始めの変数定義部分を変更すれば PopClip で使ったスクリプトがほぼそのまま使えます。
on run {input}
set source to "English|Japanese" as text -- 翻訳元言語
set target to "English|Japanese" as text -- 翻訳先言語
set input to input as string -- 入力テキスト
set configPath to "/tmp" -- 設定ファイルの保存先
set configFile to configPath & "/plamo-translate-config.json" -- 設定ファイル
set isRunning to false
try -- サーバーが起動しているか確認
- 途中省略 -
on error errMsg -- 翻訳コマンドでエラーが発生した場合
display dialog "Translation error: " & errMsg buttons {"OK"} default button "OK" with icon stop
error number -128
end try
end run

入力がない (何も選択していない) 状態でショートカットを呼び出すとクリップボードの内容を翻訳します。
そのため TextSniper 等と組み合わせれば文字が描かれた画像を翻訳することもできます。
8. 緊急処置
万が一 PLaMo-Translate OFF を使用してもサーバーが終了できなくなった場合、ターミナルを起動して
ps aux | grep -E 'PID|plamo-translate'
表示されたリストの PID を指定して強制終了させてください。
kill -9 <PID>
9. AppleScript のバグ?
クリップボードにコピーした翻訳結果をすぐに翻訳し直そうとするとエラーが出てしまいます。
10. (追記) 初回に公開したスクリプトのバグについて
現象
翻訳実行時に処理が進まなくなり、クライアントを強制終了させる以外の対処法がなくなる。
直接的要因
サーバーが既に起動していてもクライアントがサーバーの稼働を検知できず、plamo-translate が二重で起動してしまう。
原因
plamo-translate は設定ファイル (plamo-translate-config.json) を環境変数 TMPDIR で示されたパスに作成します。
調べたところ TMPDIR の内容はコマンドを実行した環境によって (特にショートカットの場合) 異なるということが分かりました。
Terminal: /var/folders/xx/yyyyyyyyyyyyyyyyyyyyyyyy/T/
LaunchAgent: /var/folders/xx/yyyyyyyyyyyyyyyyyyyyyyyy/T/
AppleScript: /var/folders/xx/yyyyyyyyyyyyyyyyyyyyyyyy/T/
Shortcuts: /var/folders/xx/yyyyyyyyyyyyyyyyyyyyyyyy/T/com.apple.shortcuts.mac-helper//
※ xx と y... の部分はユーザーやセッション、プロセスごとに異なる可能性があります。
今回の場合、サーバーの起動は LaunchAgent を使用した場合とショートカットを使用した場合の2パターンがあります。
クライアントの起動には AppleScript を使用しているため、LaunchAgent を使用してサーバーを起動した場合は (xx と y... が常に同じであることは保証されていないため絶対とは言えませんが) クライアントは設定ファイルを見つけることができます。
しかしショートカットを使用してサーバーを起動した場合、パスの違いによりクライアントは設定ファイルを見つけることが出来ません。そのためサーバーは起動していないと判断してしまうようです。
ですが作業を続けていると何かの拍子に翻訳で止まることがなくなり、システムの再起動をかけるまで普通に使用できてしまうため、不具合の内容とその原因を突き止めるまでに時間がかかってしまいました。
対策
各コマンド実行時に TMPDIR を /tmp に変更することで、常に同じ設定ファイルを参照するようにしました。
おわりに
今回作成したファイルは以下のリポジトリに保管してあります。
バグの原因については勉強になりました。
メモリたくさん欲しいです。
Discussion