LunariaJS CI/CD Integration - Automate Your Localization Workflow
Learn how to integrate LunariaJS into GitHub Actions, GitLab CI, and other CI/CD platforms, implement automatic translation status checks, automatic dashboard builds and deployments, making localization workflow fully automated.
LunariaJS CI/CD Integration - Automate Your Localization Workflow
In previous articles, we learned LunariaJS’s core features, Git workflow, and Astro Starlight integration. Today, let’s take the localization workflow to the next level — achieving complete automation through CI/CD.
💡 Official Documentation: LunariaJS Documentation - CI/CD
Value of CI/CD Integration
Why Automation?
Without CI/CD integration, localization management has these issues:
| Problem | Impact |
|---|---|
| Manual translation status checks | Time-consuming and error-prone |
| Dashboard not updated timely | Team can’t see latest status |
| Translation issues discovered late | Missing translations found only after release |
| Lack of automated notifications | Contributors don’t know translation is needed |
Continuous Localization Concept
Continuous Localization is the practice of integrating translation work into CI/CD pipelines:
Code commit → Auto-detect translation changes → Update dashboard → Notify relevant people → Deploy
Core Values:
- Instant feedback: Know translation status with every commit
- Automation: Reduce manual operations, increase efficiency
- Visibility: Team can check translation progress anytime
- Quality assurance: Ensure translation completeness before release
GitHub Actions Integration
Basic Workflow Configuration
Create .github/workflows/lunaria.yml:
name: Lunaria Dashboard
on:
push:
branches: [main]
paths:
- 'docs/**'
- 'i18n/**'
- 'lunaria.config.json'
pull_request:
branches: [main]
workflow_dispatch: # Manual trigger
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Get complete Git history
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build Lunaria Dashboard
run: npx lunaria build
- name: Upload dashboard artifact
uses: actions/upload-artifact@v4
with:
name: lunaria-dashboard
path: lunaria-dashboard/
retention-days: 7
Auto-deploy to GitHub Pages
Automatically deploy dashboard to GitHub Pages:
name: Deploy Lunaria Dashboard
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build main site
run: npm run build
- name: Build Lunaria Dashboard
run: npx lunaria build
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: './dist'
- name: Deploy to GitHub Pages
uses: actions/deploy-pages@v4
PR Translation Status Check
Automatically check translation status in Pull Requests:
name: Translation Check
on:
pull_request:
branches: [main]
jobs:
check-translations:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build Lunaria Dashboard
run: npx lunaria build --silent
- name: Check for missing translations
id: check
run: |
# Parse dashboard data, check for new missing translations
MISSING=$(node scripts/check-new-missing.js)
echo "missing=$MISSING" >> $GITHUB_OUTPUT
- name: Comment on PR
if: steps.check.outputs.missing != ''
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🌙 Translation Status Update\n\n${{ steps.check.outputs.missing }}`
})
Complete GitHub Actions Configuration
# .github/workflows/i18n.yml
name: i18n Automation
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Generate report every Monday at 9 AM
- cron: '0 9 * * 1'
workflow_dispatch:
env:
NODE_VERSION: '20'
jobs:
# Job 1: Check translation status
check:
name: Check Translation Status
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build Lunaria Dashboard
run: npx lunaria build
- name: Generate status report
id: report
run: |
# Generate status report
REPORT=$(node scripts/generate-report.js)
echo "report<<EOF" >> $GITHUB_OUTPUT
echo "$REPORT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Upload dashboard
uses: actions/upload-artifact@v4
with:
name: lunaria-dashboard
path: lunaria-dashboard/
outputs:
report: ${{ steps.report.outputs.report }}
# Job 2: Deploy dashboard (main branch only)
deploy:
name: Deploy Dashboard
runs-on: ubuntu-latest
needs: check
if: github.ref == 'refs/heads/main'
permissions:
contents: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Download dashboard
uses: actions/download-artifact@v4
with:
name: lunaria-dashboard
path: ./dashboard
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Upload to Pages
uses: actions/upload-pages-artifact@v3
with:
path: ./dashboard
- name: Deploy
id: deployment
uses: actions/deploy-pages@v4
# Job 3: Send notification (scheduled task)
notify:
name: Send Weekly Report
runs-on: ubuntu-latest
needs: check
if: github.event_name == 'schedule'
steps:
- name: Send Slack notification
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "🌙 Weekly Translation Report",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "${{ needs.check.outputs.report }}"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
GitLab CI Integration
Basic Configuration
Create .gitlab-ci.yml:
# .gitlab-ci.yml
stages:
- check
- build
- deploy
variables:
NODE_VERSION: '20'
# Cache configuration
.node-cache:
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
# Check translation status
lunaria-check:
stage: check
extends: .node-cache
image: node:${NODE_VERSION}
script:
- npm ci
- npx lunaria build
artifacts:
paths:
- lunaria-dashboard/
expire_in: 1 week
only:
- merge_requests
- main
# Build and deploy
lunaria-deploy:
stage: deploy
image: node:${NODE_VERSION}
needs:
- lunaria-check
script:
- echo "Deploying Lunaria dashboard..."
# Add your deployment script
only:
- main
GitLab Pages Integration
# .gitlab-ci.yml
image: node:20
stages:
- deploy
pages:
stage: deploy
script:
- npm ci
- npm run build
- npx lunaria build
- mv lunaria-dashboard public
artifacts:
paths:
- public
only:
- main
GitLab CI vs GitHub Actions Comparison
| Feature | GitHub Actions | GitLab CI |
|---|---|---|
| Get complete history | fetch-depth: 0 | GIT_DEPTH: 0 |
| Artifact upload | upload-artifact | artifacts.paths |
| Deploy to Pages | deploy-pages | pages job |
| Secrets | secrets.VARIABLE | variables.VARIABLE |
| Conditional execution | if: | only:/except: |
Automation Task Design
Translation Completeness Check
Create custom check script scripts/check-new-missing.js:
// scripts/check-new-missing.js
const fs = require('fs');
const path = require('path');
function checkMissingTranslations() {
// Read LunariaJS generated status data
const statusPath = path.join('lunaria-dashboard', 'data', 'status.json');
if (!fs.existsSync(statusPath)) {
console.log('No status file found');
return '';
}
const status = JSON.parse(fs.readFileSync(statusPath, 'utf8'));
// Find missing translations
const missing = [];
for (const [lang, data] of Object.entries(status.languages)) {
if (data.missing > 0) {
missing.push({
language: lang,
count: data.missing,
files: data.missingFiles || []
});
}
}
if (missing.length === 0) {
return 'All translations are up to date!';
}
// Generate report
let report = '### Missing Translations Found\n\n';
for (const item of missing) {
report += `- **${item.language}**: ${item.count} missing files\n`;
}
report += '\nPlease check the [Lunaria Dashboard](/i18n-status/) for details.';
return report;
}
console.log(checkMissingTranslations());
Outdated Translation Alert
Check for outdated translations and issue warnings:
// scripts/check-outdated.js
const { execSync } = require('child_process');
function getOutdatedTranslations() {
// Get source files updated in the last 7 days
const recentChanges = execSync(
'git log --since="7 days ago" --name-only --pretty=format: -- docs/en/',
{ encoding: 'utf8' }
);
const changedFiles = recentChanges
.split('\n')
.filter(f => f.trim())
.map(f => f.replace('docs/en/', '').replace('.md', ''));
if (changedFiles.length === 0) {
return { hasOutdated: false, files: [] };
}
return {
hasOutdated: true,
files: changedFiles,
message: `The following files were updated in the last 7 days and may need translation updates:\n${changedFiles.map(f => `- ${f}`).join('\n')}`
};
}
const result = getOutdatedTranslations();
if (result.hasOutdated) {
console.log(result.message);
process.exit(1); // Non-zero exit code will fail CI
} else {
console.log('No recent source changes requiring translation updates.');
}
Dashboard Auto-publish
Automatically publish dashboard after build:
- name: Publish Dashboard
run: |
# Copy dashboard to publish directory
cp -r lunaria-dashboard ./dist/i18n-status
# Update deployment status
echo "Dashboard published to /i18n-status/"
Notifications and Reports
Slack Notification
- name: Notify Slack
if: always()
uses: slackapi/slack-github-action@v1
with:
channel-id: 'C0123456789'
payload: |
{
"text": "Lunaria Dashboard Update",
"attachments": [
{
"color": "${{ job.status == 'success' && 'good' || 'danger' }}",
"fields": [
{
"title": "Status",
"value": "${{ job.status }}",
"short": true
},
{
"title": "Branch",
"value": "${{ github.ref_name }}",
"short": true
},
{
"title": "Dashboard URL",
"value": "<https://your-org.github.io/your-repo/i18n-status/|View Dashboard>",
"short": false
}
]
}
]
}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
PR Comment Bot
Automatically comment translation status in PRs:
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
const status = require('./lunaria-dashboard/data/status.json');
let body = '## 🌙 Translation Status\n\n';
body += '| Language | Done | Outdated | Missing | Progress |\n';
body += '|----------|------|----------|---------|----------|\n';
for (const [lang, data] of Object.entries(status.languages)) {
const progress = Math.round((data.done / data.total) * 100);
const emoji = progress >= 90 ? 'Done' : progress >= 70 ? 'Warning' : 'Error';
body += `| ${lang} | ${data.done} | ${data.outdated} | ${data.missing} | ${progress}% |\n`;
}
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
Email Report
Send periodic email reports:
- name: Send Email Report
if: github.event_name == 'schedule'
uses: dawidd6/action-send-mail@v3
with:
server_address: smtp.gmail.com
server_port: 465
username: ${{ secrets.EMAIL_USERNAME }}
password: ${{ secrets.EMAIL_PASSWORD }}
subject: Weekly Translation Report - ${{ github.repository }}
to: team@example.com
from: CI Bot
body: |
Hi Team,
Here's the weekly translation status report:
${{ needs.check.outputs.report }}
View the full dashboard: https://your-org.github.io/your-repo/i18n-status/
Best regards,
CI Bot
CI/CD Best Practices
1. Conditional Triggers
Only trigger when relevant files change:
on:
push:
branches: [main]
paths:
- 'docs/**'
- 'i18n/**'
- 'lunaria.config.json'
- '.github/workflows/lunaria.yml'
2. Cache Optimization
Use caching to speed up builds:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # Enable npm cache
- name: Cache Lunaria output
uses: actions/cache@v4
with:
path: .lunaria-cache
key: lunaria-${{ hashFiles('docs/**', 'i18n/**') }}
3. Failure Strategy
Set reasonable failure strategies:
jobs:
check:
continue-on-error: true # Translation check failure doesn't block deployment
deploy:
needs: check
if: always() && needs.check.result == 'success'
4. Parallel Execution
Execute multiple check tasks in parallel:
jobs:
check-missing:
# ...
check-outdated:
# ...
report:
needs: [check-missing, check-outdated]
# ...
5. Security Best Practices
# Use minimal permissions
permissions:
contents: read
pull-requests: write
# Don't expose secrets
env:
DASHBOARD_URL: ${{ secrets.DASHBOARD_URL }} # Don't expose in logs
Summary
Through CI/CD integration, LunariaJS can achieve fully automated localization workflows:
| Feature | Implementation |
|---|---|
| Auto-detect translation changes | GitHub Actions / GitLab CI |
| Auto-build dashboard | Triggered on every commit |
| Auto-deploy | GitHub Pages / GitLab Pages |
| Auto-notify | Slack / Email / PR comments |
| Periodic reports | Scheduled jobs |
Key Points:
- Use
fetch-depth: 0to get complete Git history - Configure conditional triggers to reduce unnecessary builds
- Leverage caching to speed up CI runs
- Set up reasonable notification mechanisms
Next Steps
Congratulations on completing the LunariaJS introductory series! Starting from the next article, we’ll enter the Deep Dive section, exploring:
- Part 8: @lunariajs/core Source Code Deep Dive (8,000-15,000 words)
- Part 9: Advanced Configuration and Custom Strategies (8,000-15,000 words)
- Part 10: Complete Enterprise-level Implementation (8,000-15,000 words)
Stay tuned!
💡 Recommended Reading: