Deep Dive into @lunariajs/core Source Code - Understanding LunariaJS Core Architecture
Deep dive into LunariaJS core library architecture design and implementation principles, understanding file parsing, status tracking, configuration handling and other core modules from source code level, laying the foundation for custom extensions and advanced usage.
Deep Dive into @lunariajs/core Source Code - Understanding LunariaJS Core Architecture
In the previous seven introductory articles, we comprehensively learned LunariaJS installation, configuration, CLI commands, dashboard, Git workflow, Starlight integration, and CI/CD integration. Now, let’s dive into the source code level to understand LunariaJS’s core architecture and implementation principles.
Official Documentation: LunariaJS Documentation - API Reference
Core Architecture Overview
Overall Architecture Diagram
LunariaJS’s core architecture can be summarized in the following layers:
+---------------------------------------------------------------+
| CLI Layer |
| (lunaria init/build/preview) |
+---------------------------------------------------------------+
| API Layer |
| (Public API for external use) |
+---------------------------------------------------------------+
| Core Modules |
| +--------------+ +--------------+ +--------------+ |
| | Config | | File | | Status | |
| | System | | Parsers | | Tracker | |
| +--------------+ +--------------+ +--------------+ |
| +--------------+ +--------------+ +--------------+ |
| | Git | | Dashboard | | Reporter | |
| | Client | | Generator | | | |
| +--------------+ +--------------+ +--------------+ |
+---------------------------------------------------------------+
| Infrastructure |
| (File System, Git, Logger, Utils) |
+---------------------------------------------------------------+
Core Module Responsibilities
| Module | Responsibility | Core Files |
|---|---|---|
| Config System | Configuration loading, validation, default value handling | config.ts |
| File Parsers | Parse different formats of localization files | parsers/ |
| Status Tracker | Track translation status (done/outdated/missing) | status.ts |
| Git Client | Git operation wrapper (get commit history, file status) | git.ts |
| Dashboard Generator | Generate static HTML dashboard | dashboard/ |
| Reporter | Generate status reports and log output | reporter.ts |
Tech Stack Choices
LunariaJS chose the following tech stack:
| Technology | Purpose | Reason for Choice |
|---|---|---|
| TypeScript | Primary language | Type safety, better IDE support |
| Zod | Schema validation | Configuration file validation |
| Vite | Build tool | Fast ES module support |
| simple-git | Git operations | Node.js Git client |
| handlebars | Template engine | Dashboard HTML generation |
Directory Structure
@lunariajs/core/
+-- src/
| +-- index.ts # Public API entry
| +-- config.ts # Configuration system
| +-- status.ts # Status tracking
| +-- git.ts # Git operations
| +-- reporter.ts # Report generation
| +-- parsers/ # File parsers
| | +-- index.ts
| | +-- json.ts
| | +-- yaml.ts
| | +-- markdown.ts
| +-- dashboard/ # Dashboard generation
| | +-- index.ts
| | +-- templates/
| | +-- assets/
| +-- types/ # Type definitions
| | +-- config.ts
| | +-- status.ts
| +-- utils/ # Utility functions
| +-- file.ts
| +-- logger.ts
+-- package.json
+-- tsconfig.json
+-- README.md
Configuration System
Configuration Type Definitions
LunariaJS uses TypeScript to define strict configuration types:
// src/types/config.ts
/**
* Supported file formats
*/
export type FileFormat = 'json' | 'yaml' | 'md' | 'csv';
/**
* Language configuration
*/
export interface LocaleConfig {
/** Language label (e.g., 'en', 'zh-cn') */
label: string;
/** Language direction */
dir?: 'ltr' | 'rtl';
/** Custom data */
[key: string]: unknown;
}
/**
* File pattern configuration
*/
export interface FilePattern {
/** Source language file path pattern */
sourcePath: string;
/** Translation file path pattern */
localizationPath: string;
/** Include file glob patterns */
include?: string[];
/** Exclude file glob patterns */
exclude?: string[];
}
/**
* Dashboard configuration
*/
export interface DashboardConfig {
/** Output directory */
outputDir: string;
/** Dashboard title */
title?: string;
/** Dashboard description */
description?: string;
/** UI language */
uiLanguage?: string;
/** Custom CSS path */
customCss?: string;
/** Site URL (for SEO) */
site?: string;
}
/**
* LunariaJS complete configuration
*/
export interface LunariaConfig {
/** Source language */
sourceLanguage: string;
/** All supported languages */
languages: string[];
/** Language configuration mapping */
locales?: Record<string, LocaleConfig>;
/** File pattern list */
files: FilePattern[];
/** Dashboard configuration */
dashboard?: DashboardConfig;
/** Ignore keywords (for detecting placeholder translations) */
ignoreKeywords?: string[];
}
Configuration Loading Mechanism
Configuration loading is divided into three phases:
// src/config.ts
import { promises as fs } from 'fs';
import { pathExists } from './utils/file';
import { LunariaConfig } from './types/config';
import { defaultConfig } from './config/defaults';
/**
* Configuration loader
*/
export async function loadConfig(
configPath: string = 'lunaria.config.json'
): Promise<LunariaConfig> {
// Phase 1: Try to load user configuration
const userConfig = await loadUserConfig(configPath);
// Phase 2: Merge with default configuration
const mergedConfig = mergeConfig(defaultConfig, userConfig);
// Phase 3: Validate configuration
const validatedConfig = validateConfig(mergedConfig);
return validatedConfig;
}
Configuration Validation
Using Zod for strict configuration validation:
// src/config/validation.ts
import { z } from 'zod';
/**
* Configuration Schema definition
*/
const LunariaConfigSchema = z.object({
sourceLanguage: z.string().min(1, 'sourceLanguage is required'),
languages: z.array(z.string()).min(1, 'At least one language is required'),
files: z.array(
z.object({
sourcePath: z.string(),
localizationPath: z.string(),
include: z.array(z.string()).optional(),
exclude: z.array(z.string()).optional(),
})
).min(1, 'At least one file pattern is required'),
dashboard: z.object({
outputDir: z.string().default('lunaria-dashboard'),
title: z.string().optional(),
description: z.string().optional(),
}).optional(),
});
File Parsers
Parser Interface Design
LunariaJS defines a unified parser interface:
// src/parsers/types.ts
/**
* Localized file content
*/
export interface LocalizedContent {
/** File path */
path: string;
/** Language code */
lang: string;
/** Key-value content */
entries: Record<string, string>;
/** Raw content */
raw: string;
/** Last modified time */
lastModified?: Date;
}
/**
* File parser interface
*/
export interface FileParser {
/** Supported file extensions */
extensions: string[];
/** Parse file content */
parse(content: string, path: string): Promise<LocalizedContent>;
/** Serialize content (for file generation) */
stringify(data: Record<string, string>): string;
}
Status Tracking Engine
Status Calculation Core Logic
Status tracking is LunariaJS’s core functionality:
// src/status.ts
import { LunariaConfig } from './types/config';
import { FileStatus, TranslationStatus } from './types/status';
import { getFileLastModified } from './git';
/**
* Calculate translation status for a single file
*/
export async function calculateFileStatus(
sourcePath: string,
translationPath: string,
lang: string,
config: LunariaConfig
): Promise<FileStatus> {
// Check if translation file exists
const translationExists = await fileExists(translationPath);
if (!translationExists) {
return {
path: translationPath,
lang,
status: 'missing',
sourcePath,
};
}
// Get last modified times
const sourceLastModified = await getFileLastModified(sourcePath);
const translationLastModified = await getFileLastModified(translationPath);
// Compare timestamps
if (translationLastModified >= sourceLastModified) {
return {
path: translationPath,
lang,
status: 'done',
sourcePath,
lastModified: translationLastModified,
};
}
// Translation outdated
const daysOutdated = Math.floor(
(sourceLastModified.getTime() - translationLastModified.getTime()) /
(1000 * 60 * 60 * 24)
);
return {
path: translationPath,
lang,
status: 'outdated',
sourcePath,
lastModified: translationLastModified,
sourceLastModified,
daysOutdated,
};
}
Dashboard Generator
Template System
LunariaJS uses Handlebars template engine to generate dashboards:
// src/dashboard/generator.ts
import Handlebars from 'handlebars';
import { TranslationStatus } from '../types/status';
// Register Handlebars helpers
Handlebars.registerHelper('progressBar', (progress: number) => {
const color = progress >= 90 ? 'green' : progress >= 70 ? 'yellow' : 'red';
return new Handlebars.SafeString(
`<div class="progress-bar">
<div class="progress-fill ${color}" style="width: ${progress}%"></div>
</div>`
);
});
Handlebars.registerHelper('statusIcon', (status: string) => {
const icons: Record<string, string> = {
done: 'Done',
outdated: 'Warning',
missing: 'Error',
};
return icons[status] || '?';
});
API Design Analysis
Public API
LunariaJS exports the following public APIs:
// src/index.ts
export { loadConfig } from './config';
export { calculateAllStatus, calculateProgress } from './status';
export { generateDashboard } from './dashboard/generator';
export { getFileLastModified, getFileHistory } from './git';
export { parseFile, getParser } from './parsers';
// Type exports
export type { LunariaConfig, FilePattern, DashboardConfig } from './types/config';
export type { TranslationStatus, FileStatus } from './types/status';
export type { LocalizedContent, FileParser } from './parsers/types';
Usage Example
import {
loadConfig,
calculateAllStatus,
generateDashboard,
calculateProgress,
} from '@lunariajs/core';
async function main() {
// 1. Load configuration
const config = await loadConfig('lunaria.config.json');
// 2. Calculate translation status
const status = await calculateAllStatus(config);
// 3. Generate dashboard
await generateDashboard(status, config.dashboard?.outputDir || 'lunaria-dashboard');
// 4. Output progress report
for (const lang of Object.keys(status.languages)) {
const progress = calculateProgress(status, lang);
console.log(`${lang}: ${progress}% complete`);
}
}
main().catch(console.error);
Summary
This chapter covered @lunariajs/core’s core architecture in depth:
| Module | Core Function | Key Technologies |
|---|---|---|
| Configuration system | Load, validate, merge configs | Zod Schema validation |
| File parsers | Parse JSON/YAML/Markdown | Unified interface design |
| Status tracking | Calculate translation status | Git timestamp comparison |
| Git client | Wrap Git operations | simple-git |
| Dashboard generation | Generate static HTML | Handlebars templates |
Key Takeaways:
- Uses TypeScript for type safety
- Modular design with clear responsibilities
- Zod for configuration validation
- Git history for tracking translation status
- Template engine for dashboard generation
Next Steps
In the next article, we’ll explore LunariaJS advanced configuration and custom strategies, learning how to:
- Handle complex enterprise configuration scenarios
- Implement multi-repository localization management
- Design custom localization strategies
- Optimize performance for large projects
Stay tuned!
Note: The code examples in this article are simplified versions for demonstration purposes. For complete code, please refer to the LunariaJS GitHub repository.
Recommended Reading: