ブログ

LunariaJS + Git:バージョン管理ベースのローカライズワークフロー

LunariaJSがGitを使ってローカライズ変更を追跡する方法を解説。Gitコミット履歴で翻訳更新を特定し、古いコンテンツを検出し、チームコラボレーションとシームレスに統合されたローカライズワークフローを実現する方法を学びます。

LibDoc Team 2026年3月6日 LunariaJS 連載 54 分で読める
#LunariaJS #Git #バージョン管理 #ワークフロー #チームコラボレーション

LunariaJS + Git:バージョン管理ベースのローカライズワークフロー

これまでの記事で、LunariaJSのインストール、設定、ダッシュボードの使用方法を紹介しました。お気づきかもしれませんが、LunariaJSのコア機能の1つはGitベースのワークフローです。今日は、LunariaJSがGitを活用してローカライズ変更を追跡する方法と、効率的なチームコラボレーションワークフローの設計方法について詳しく解説します。

💡 公式ドキュメントLunariaJS 日本語ドキュメント - Gitワークフロー

なぜGit統合が必要?

従来のローカライズ管理の課題

Git統合がない場合、翻訳状態の管理には通常以下が必要:

方法1:スプレッドシートの手動管理

ファイル中国語日本語韓国語
index.md
getting-started.md⚠️⚠️
configuration.md

問題

  • スプレッドシートが実際のファイルと同期しない
  • 「⚠️」が具体的にどれくらい遅れているか不明
  • スプレッドシート更新は余分なメンテナンス負担

方法2:翻訳プラットフォームのバージョン管理

一部のオンライン翻訳プラットフォーム(Crowdinなど)には独自のバージョン管理システムがあります。

問題

  • コードリポジトリと分離
  • 同期メカニズムの設定が必要
  • バージョン不一致の可能性

方法3:ファイル内マーカーの追加

<!-- TODO: Translate to Chinese -->
<!-- LAST_UPDATED: 2026-02-20 -->
<!-- STATUS: OUTDATED -->

問題

  • ファイル内容を汚染
  • マーカーの更新を忘れがち
  • バッチ分析が困難

LunariaJSのGit統合の利点

LunariaJSは異なるアプローチを選択:Gitコミット履歴を直接使用して翻訳状態を判断

コアの利点

利点説明
余分なマーカー不要ファイル自体がデータソース
自動同期Git履歴がコードと完全に同期
精密な追跡各変更の時刻と作者を把握
チームフレンドリー既存のGitワークフローに統合

Git追跡メカニズムの詳細

基本原理

LunariaJSは以下の手順で翻訳状態を判断:

1. ファイルの最終更新時刻を取得

git logコマンドで各ファイルの最終コミットを取得:

git log -1 --format="%H %ct" -- path/to/file.md

2. ソースファイルと翻訳ファイルのタイムスタンプ比較

ソースファイル (en/getting-started.md):  2026-02-28 14:30
翻訳ファイル (zh-cn/getting-started.md): 2026-02-20 10:15

時間差: 8日
状態: 古い (Outdated)

3. 状態レポート生成

タイムスタンプ比較に基づき、各翻訳ファイルの状態を生成。

ファイル変更検出アルゴリズム

LunariaJSは以下のアルゴリズムでファイル変更を検出:

// 簡略化されたアルゴリズムロジック
function getTranslationStatus(sourceFile: File, translationFile: File): Status {
  // ケース1: 翻訳ファイルが存在しない
  if (!translationFile.exists()) {
    return 'missing';
  }

  // 最終更新時刻を取得
  const sourceLastModified = getLastCommitTime(sourceFile);
  const translationLastModified = getLastCommitTime(translationFile);

  // ケース2: 翻訳がソースと同じか新しい
  if (translationLastModified >= sourceLastModified) {
    return 'done';
  }

  // ケース3: ソースが翻訳より新しい
  return 'outdated';
}

Gitコミットタイムスタンプ解析

# ファイルの最終コミットを取得
$ git log -1 --format="%H %ct %s" -- docs/en/getting-started.md

abc1234567 1709123400 "Update getting-started documentation"

出力解析

  • %H:完全なコミットハッシュ
  • %ct:Unixタイムスタンプ
  • %s:コミットメッセージ

古い翻訳検出の原理

タイムスタンプ比較戦略

LunariaJSは「最終更新時刻」戦略で翻訳が古いかどうかを判断:

タイムライン例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━▶
         │                      │                    │
      2月20日                2月25日               2月28日
         │                      │                    │
    中国語翻訳更新           英語ソース更新         現在時刻
    (commit: def5678)      (commit: abc1234)
         │                      │
         └──────────────────────┘
                時間差 8日

             状態: 古い 🟡

なぜ内容比較を使わない?

なぜgit diffで内容を直接比較しないのか疑問に思うかもしれません。

内容比較の問題

  • 計算コストが高い(各ファイルを読み込んで解析が必要)
  • 構造は同じだが内容が異なる場合に対応できない
  • 大規模プロジェクトでパフォーマンスに影響

タイムスタンプ比較の利点

  • 計算コストが低い(Gitメタデータのみ読み取り)
  • パフォーマンスが安定、ファイルサイズの影響を受けない
  • 意味が明確:ソース更新後の翻訳は「古い」

特殊ケースの処理

ケース1:ソースと翻訳が同時に更新

# 同じコミットでソースと翻訳を更新
$ git log --oneline -- docs/en/guide.md docs/zh-cn/guide.md
abc1234 (HEAD) Update guide documentation

結果:状態はdone

ケース2:翻訳ファイルのみ更新

# 翻訳のみ更新、ソースは未変更
$ git log -1 -- docs/zh-cn/guide.md
abc1234 (HEAD) Update Chinese translation
$ git log -1 -- docs/en/guide.md
def5678 (HEAD~1) Original guide

結果:状態はdone

ケース3:フォーマット調整のみ(内容に影響なし)

# ソースファイルがフォーマット調整のみ
$ git show abc1234 --stat
docs/en/guide.md | 2 +-
# スペースや改行の調整のみ

結果:状態はoutdated ⚠️(保守的な戦略)

💡 これはLunariaJSの保守的な設計選択です。翻訳が有効であることを確認できる場合は、コミットメッセージに[skip lunaria]マーカーを追加できます。

ブランチ戦略とローカライズ

メインブランチでの翻訳管理

ほとんどのプロジェクトはメインブランチ(mainまたはmaster)で翻訳を管理:

main

  ├── docs/en/           # ソース言語(英語)
  │   ├── index.md
  │   └── guide.md

  ├── docs/zh-cn/        # 中国語翻訳
  │   ├── index.md
  │   └── guide.md

  └── docs/ja/           # 日本語翻訳
      ├── index.md
      └── guide.md

LunariaJS設定

{
  "sourceLanguage": "en",
  "languages": ["en", "zh-cn", "ja"],
  "files": [
    {
      "sourcePath": "docs/en/{slug}.md",
      "localizationPath": "docs/{lang}/{slug}.md"
    }
  ]
}

機能ブランチでの翻訳処理

新機能開発時、通常は機能ブランチを作成:

main

  └── feature/new-api-docs

        └── docs/en/api/new-endpoint.md  # 新規ソースファイル

問題:新機能ブランチの翻訳はどう扱う?

戦略1:機能ブランチでは翻訳しない

  • ソースファイルは機能ブランチで先行して完成
  • メインブランチにマージ後、翻訳を開始
  • メリット:翻訳の競合を回避
  • デメリット:ユーザーが欠落した翻訳を見る

戦略2:同時翻訳

feature/new-api-docs

  ├── docs/en/api/new-endpoint.md
  ├── docs/zh-cn/api/new-endpoint.md
  └── docs/ja/api/new-endpoint.md
  • メリット:機能ローンチ時に翻訳も完了
  • デメリット:翻訳の時間調整が必要

戦略3:ドラフトマーカーの使用

---
title: New API Endpoint
draft: true  # ドラフトとしてマーク、公開サイトには表示しない
---
  • ソース完成後、ドラフトマーカーを削除
  • 翻訳ファイルもドラフトマーカーを使用可能

マージ時の翻訳競合解決

ソース更新と翻訳更新が競合した場合:

# シナリオ:メインブランチでソース更新、PRブランチで翻訳更新
$ git merge feature/update-zh-translation
CONFLICT (content): Merge conflict in docs/zh-cn/guide.md

解決手順

  1. 競合内容を特定
<<<<<<< HEAD
这是主分支的更新内容
=======
这是翻译分支的内容
>>>>>>> feature/update-zh-translation
  1. 競合の性質を評価

    • 翻訳関連の内容か?
    • ソースファイルに何か変更があったか?
  2. 競合を解決

    • 翻訳更新の場合:翻訳ブランチの内容を保持
    • ソースに新規コンテンツがある場合:マージ後に再翻訳
  3. 翻訳の一貫性を検証

# ダッシュボードをビルドして状態を確認
npx lunaria build --verbose

チームコラボレーションワークフロー

翻訳貢献者ワークフロー

シナリオ:コミュニティ貢献者が翻訳を手伝いたい

ステップ1:ダッシュボードを確認

プロジェクトのLunariaJSダッシュボードにアクセスし、翻訳が必要なファイルを見つける。

ステップ2:Forkしてブランチを作成

# プロジェクトをFork後
git clone https://github.com/your-username/project-name.git
cd project-name
git checkout -b translate/zh-cn-guide

ステップ3:ファイルを翻訳

# 翻訳ファイルを作成または更新
# docs/zh-cn/guide.md

ステップ4:コミットしてPRを作成

git add docs/zh-cn/guide.md
git commit -m "Translate guide to Chinese"
git push origin translate/zh-cn-guide

ステップ5:PRレビュー

メンテナーが翻訳品質と正確性をレビュー。

コードレビューでの翻訳チェック

PRレビュー時に翻訳状態チェックを追加:

# .github/workflows/translation-check.yml
name: Translation Check

on: [pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # 完全な履歴を取得

      - name: Build Lunaria Dashboard
        run: |
          npm ci
          npx lunaria build

      - name: Check Translation Status
        run: |
          # 新規欠落翻訳があるかチェック
          node scripts/check-new-missing.js

翻訳更新PRフロー

自動化フロー

ソースファイル更新


CIが古い翻訳を検出


翻訳更新Issueを作成


翻訳貢献者が担当


翻訳更新PRを提出


レビュー&マージ


ダッシュボード更新 ✅

Issue自動作成例

大量の古い翻訳が検出された場合、自動的にIssueを作成可能:

## 🌙 翻訳同期リマインダー

### 概要
- 古い翻訳数: 12
- 影響言語: 中国語 (5), 日本語 (4), 韓国語 (3)

### 更新が必要なファイル

| ファイル | 言語 | 遅延日数 |
|------|------|----------|
| getting-started.md | 中国語 | 8 |
| configuration.md | 日本語 | 5 |
| api/overview.md | 韓国語 | 3 |

### アクション
各翻訳貢献者は関連する翻訳を担当し、更新してください。

---
*このIssueはLunariaJSにより自動生成されました*

Git統合のベストプラクティス

1. コミット粒度を適切に保つ

推奨

# 各翻訳ファイルを個別にコミット
git add docs/zh-cn/guide.md
git commit -m "Translate guide to Chinese"

# または関連ファイルをまとめてコミット
git add docs/zh-cn/
git commit -m "Update Chinese translations for v2.0"

非推奨

# ソースコードと翻訳を混ぜたコミット
git add .
git commit -m "Various updates"

2. 意味のあるコミットメッセージを使用

推奨形式

[i18n/zh-cn] Translate guide.md

- Translate introduction section
- Update code examples
- Fix terminology consistency

Related: #123

3. Git Blameで翻訳履歴を追跡

# 翻訳ファイルの変更履歴を表示
git blame docs/zh-cn/guide.md

# 特定行の最終更新を確認
git blame -L 10,20 docs/zh-cn/guide.md

4. Git Hooksで自動化

# pre-commit hook
#!/bin/bash

# ソースファイルが更新されたが翻訳が更新されていないかチェック
npm run lunaria:check-outdated

if [ $? -ne 0 ]; then
  echo "Warning: Some translations are outdated!"
  echo "Run 'npx lunaria build' to see details."
fi

5. .gitattributesの設定

# .gitattributes
# 翻訳ファイルの言語をマーク
docs/zh-cn/*.md linguist-language=Markdown
docs/ja/*.md linguist-language=Markdown

# git diffで変更をより良く表示
*.md text eol=lf

高度なGit統合テクニック

1. Gitエイリアスで操作を簡略化

# ~/.gitconfig
[alias]
    lunaria = "!f() { npx lunaria \"$@\"; }; f"
    i18n-status = "!f() { npx lunaria build && npx lunaria preview; }; f"

使用:

git lunaria build
git i18n-status

2. 複数リポジトリ翻訳管理

Monorepoプロジェクトの場合:

{
  "files": [
    {
      "sourcePath": "packages/core/docs/{slug}.md",
      "localizationPath": "packages/core/i18n/{lang}/{slug}.md"
    },
    {
      "sourcePath": "packages/cli/docs/{slug}.md",
      "localizationPath": "packages/cli/i18n/{lang}/{slug}.md"
    }
  ]
}

3. サブモジュールで翻訳管理

# 翻訳サブモジュールを追加
git submodule add https://github.com/org/translations.git i18n

# 翻訳を更新
git submodule update --remote i18n

4. 翻訳ブランチ戦略

main

  ├── i18n/zh-cn    # 中国語翻訳ブランチ

  ├── i18n/ja       # 日本語翻訳ブランチ

  └── i18n/ko       # 韓国語翻訳ブランチ

各翻訳ブランチは対応する言語メンテナーが管理し、定期的にメインブランチにマージ。

よくある問題と解決策

Q1:Git履歴が不完全で状態が誤っている

問題:シャロークローン(shallow clone)で完全な履歴がない。

解決策

# 完全な履歴を取得
git fetch --unshallow

# またはCIで設定
- uses: actions/checkout@v4
  with:
    fetch-depth: 0  # 完全な履歴

Q2:大規模ファイル翻訳追跡のパフォーマンス問題

問題:プロジェクトファイルが多すぎてビルドが遅い。

解決策

{
  "files": [
    {
      "sourcePath": "docs/{slug}.md",
      "localizationPath": "i18n/{lang}/docs/{slug}.md",
      "include": ["**/*.md"],
      "exclude": ["**/draft/**", "**/internal/**"]
    }
  ]
}

Q3:ファイル名変更後に状態が消失

問題:ファイル名変更後、Git履歴追跡が切断。

解決策

# git mvで履歴を保持
git mv docs/old-name.md docs/new-name.md

まとめ

LunariaJSとGitの深い統合は強力なローカライズ管理機能をもたらします:

特徴価値
タイムスタンプ比較古い翻訳を自動的に検出
余分なマーカー不要ファイルをクリーンに保つ
チームコラボレーション既存のワークフローに統合
履歴追跡各変更を追跡可能
CI/CD統合翻訳チェックの自動化

重要なポイント

  • Gitコミット時刻は翻訳状態判断のコア基準
  • 意味のあるワークフローでブランチとマージを処理
  • CI/CDで翻訳状態チェックを自動化
  • 良いコミット習慣を維持して追跡を容易に

次のステップ

次の記事では、LunariaJSとAstro Starlightの完璧な統合について解説し、以下を学びます:

  • @lunariajs/starlightのインストールと設定
  • ダッシュボードをドキュメントサイトに埋め込み
  • 3言語ドキュメントサイトの実践
  • 一般的な統合問題の解決

お楽しみに!


💡 おすすめ読書