博客
LunariaJS 高级配置:打造企业级本地化管理方案
探索 LunariaJS 的高级配置选项和自定义本地化策略,学习多仓库支持、自定义状态规则、复杂文件结构处理等企业级场景的解决方案。
LibDoc Team 2026年3月6日 LunariaJS 专栏 102 分钟阅读
#LunariaJS
#高级配置
#企业级
#自定义策略
#Monorepo
LunariaJS 高级配置:打造企业级本地化管理方案
在上一篇文章中,我们深入剖析了 @lunariajs/core 的源码架构。今天,让我们将这些知识应用到实践中,探索 LunariaJS 的高级配置选项,解决企业级场景中的复杂本地化管理需求。
💡 官方文档:LunariaJS 中文文档 - 高级配置
企业级场景挑战
典型企业级需求
企业级项目通常面临以下本地化挑战:
| 挑战 | 描述 | 影响 |
|---|---|---|
| 多仓库管理 | 代码分布在多个 Git 仓库 | 翻译状态难以统一追踪 |
| 复杂文件结构 | 不同模块有不同的目录结构 | 配置复杂,容易出错 |
| 自定义工作流 | 需要适配现有的开发流程 | 标准配置无法满足需求 |
| 权限控制 | 不同团队有不同的访问权限 | 需要细粒度的权限管理 |
| 大规模文件 | 数百甚至数千个翻译文件 | 性能成为瓶颈 |
| 多源语言 | 不同模块可能有不同的源语言 | 状态计算逻辑复杂 |
本章学习目标
通过本章,你将学会:
- ✅ 配置复杂的多仓库项目
- ✅ 设计自定义状态判断规则
- ✅ 优化大型项目的性能
- ✅ 集成企业工具和系统
- ✅ 实现高级安全和权限控制
高级配置选项
自定义状态规则
LunariaJS 允许你自定义翻译状态的判断逻辑:
// lunaria.config.ts
import { defineConfig } from '@lunariajs/core';
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko'],
// 自定义状态判断
statusRules: {
// 自定义"过时"的判定条件
outdated: {
// 天数阈值:源文件比翻译新多少天才算过时
dayThreshold: 7, // 默认 0,这里设为 7 天
// 或者使用自定义函数
customCheck: async (source, translation) => {
// 检查源文件是否有重大变更
const changes = await getSignificantChanges(source.path);
return changes.length > 0;
},
},
// 自定义"缺失"的判定条件
missing: {
// 忽略某些文件模式
ignorePatterns: ['**/internal/**', '**/draft/**'],
// 或者使用自定义函数
customCheck: (sourcePath, translationPath) => {
// 检查是否需要翻译(某些文件可能不需要翻译)
const content = fs.readFileSync(sourcePath, 'utf-8');
return !content.includes('<!-- no-translate -->');
},
},
},
files: [
{
sourcePath: 'docs/{slug}.md',
localizationPath: 'i18n/{lang}/{slug}.md',
},
],
});
复杂路径映射
处理复杂的项目结构:
// lunaria.config.ts
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko'],
files: [
// 文档文件
{
sourcePath: 'docs/guides/{slug}.md',
localizationPath: 'docs/{lang}/guides/{slug}.md',
include: ['**/*.md'],
exclude: ['**/draft/**'],
},
// API 参考文档
{
sourcePath: 'docs/api/{category}/{slug}.md',
localizationPath: 'docs/{lang}/api/{category}/{slug}.md',
},
// UI 翻译文件(JSON)
{
sourcePath: 'src/locales/en/{module}.json',
localizationPath: 'src/locales/{lang}/{module}.json',
},
// 配置文件
{
sourcePath: 'config/en/{slug}.yaml',
localizationPath: 'config/{lang}/{slug}.yaml',
},
],
});
多源文件配置
某些项目可能有多个源语言目录:
// lunaria.config.ts
export default defineConfig({
// 主源语言
sourceLanguage: 'en',
// 次要源语言(用于特定模块)
secondarySourceLanguages: {
'packages/japanese-sdk': 'ja', // 这个包的源语言是日语
},
languages: ['en', 'ja', 'zh-cn', 'ko'],
files: [
// 主项目 - 英语为源语言
{
sourcePath: 'docs/{slug}.md',
localizationPath: 'docs/{lang}/{slug}.md',
sourceLanguage: 'en', // 显式指定
},
// Japanese SDK - 日语为源语言
{
sourcePath: 'packages/japanese-sdk/docs/{slug}.md',
localizationPath: 'packages/japanese-sdk/docs/{lang}/{slug}.md',
sourceLanguage: 'ja', // 覆盖全局配置
},
],
});
条件化处理
根据条件动态调整配置:
// lunaria.config.ts
const isProduction = process.env.NODE_ENV === 'production';
const isCI = process.env.CI === 'true';
export default defineConfig({
sourceLanguage: 'en',
// 根据环境调整语言列表
languages: isProduction
? ['en', 'zh-cn', 'ja', 'ko', 'es', 'fr', 'de']
: ['en', 'zh-cn'], // 开发环境只追踪两种语言
files: [
{
sourcePath: 'docs/{slug}.md',
localizationPath: 'i18n/{lang}/{slug}.md',
// CI 环境排除草稿文件
exclude: isCI ? ['**/draft/**', '**/wip/**'] : [],
},
],
dashboard: {
outputDir: isProduction ? 'dist/i18n-status' : 'public/i18n-status',
title: isProduction ? 'Production i18n Status' : 'Development i18n Status',
},
});
多仓库本地化管理
Monorepo 场景配置
对于 Monorepo 项目(如使用 pnpm workspaces 或 Turborepo):
my-monorepo/
├── packages/
│ ├── core/
│ │ ├── docs/
│ │ │ └── en/
│ │ └── i18n/
│ │ ├── zh-cn/
│ │ └── ja/
│ ├── cli/
│ │ ├── docs/
│ │ │ └── en/
│ │ └── i18n/
│ │ ├── zh-cn/
│ │ └── ja/
│ └── ui/
│ ├── docs/
│ │ └── en/
│ └── i18n/
│ ├── zh-cn/
│ └── ja/
├── lunaria.config.ts
└── package.json
配置示例:
// lunaria.config.ts
import { defineConfig } from '@lunariajs/core';
import { glob } from 'glob';
// 自动发现所有包
const packages = await glob('packages/*');
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko'],
// 为每个包生成独立的文件配置
files: packages.flatMap(pkg => [
{
sourcePath: `${pkg}/docs/{slug}.md`,
localizationPath: `${pkg}/i18n/{lang}/{slug}.md`,
// 使用包名作为分组
group: pkg.replace('packages/', ''),
},
]),
dashboard: {
outputDir: 'docs/i18n-status',
title: 'My Monorepo - Translation Status',
// 按包分组显示
groupBy: 'group',
},
});
多仓库统一仪表板
对于多个独立的 Git 仓库,可以创建一个”聚合”项目:
i18n-aggregator/
├── lunaria.config.ts
├── package.json
└── repos/
├── main-docs/ # 主文档仓库
├── api-docs/ # API 文档仓库
└── blog-content/ # 博客内容仓库
聚合配置:
// lunaria.config.ts
import { defineConfig } from '@lunariajs/core';
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko'],
// 聚合多个仓库
repositories: [
{
name: 'main-docs',
path: './repos/main-docs',
files: [
{
sourcePath: 'docs/{slug}.md',
localizationPath: 'i18n/{lang}/{slug}.md',
},
],
},
{
name: 'api-docs',
path: './repos/api-docs',
files: [
{
sourcePath: 'src/content/docs/{slug}.md',
localizationPath: 'src/content/docs/{lang}/{slug}.md',
},
],
},
{
name: 'blog-content',
path: './repos/blog-content',
files: [
{
sourcePath: 'posts/{slug}.md',
localizationPath: 'posts/{lang}/{slug}.md',
},
],
},
],
dashboard: {
outputDir: 'public/i18n-status',
title: 'All Projects - Translation Status',
},
});
跨仓库依赖处理
处理跨仓库的翻译依赖:
// lunaria.config.ts
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko'],
// 定义翻译依赖
dependencies: {
// api-docs 的翻译依赖于 main-docs 的翻译
'api-docs': ['main-docs'],
// blog 的翻译依赖于 main-docs 和 api-docs
'blog-content': ['main-docs', 'api-docs'],
},
// 依赖检查
checkDependencies: true,
// 依赖不满足时的处理
onDependencyMissing: 'warn', // 'warn' | 'error' | 'ignore'
files: [
// ...
],
});
自定义本地化策略
策略接口设计
定义自定义本地化策略的接口:
// src/strategies/types.ts
import { TranslationStatus, FileInfo } from '@lunariajs/core';
/**
* 本地化策略接口
*/
export interface LocalizationStrategy {
/** 策略名称 */
name: string;
/** 策略描述 */
description: string;
/**
* 计算翻译状态
*/
calculateStatus(
source: FileInfo,
translation: FileInfo | null,
context: StrategyContext
): Promise<TranslationStatus>;
/**
* 是否需要翻译
*/
needsTranslation?(
source: FileInfo,
context: StrategyContext
): Promise<boolean>;
/**
* 获取翻译优先级
*/
getPriority?(
source: FileInfo,
translation: FileInfo | null,
context: StrategyContext
): Promise<'high' | 'medium' | 'low'>;
}
/**
* 策略上下文
*/
export interface StrategyContext {
/** 语言代码 */
language: string;
/** 项目配置 */
config: LunariaConfig;
/** Git 信息 */
git: {
lastCommit: string;
author: string;
date: Date;
};
/** 自定义数据 */
data?: Record<string, unknown>;
}
实现自定义策略
创建基于内容复杂度的策略:
// src/strategies/content-complexity.ts
import { LocalizationStrategy, StrategyContext, FileInfo } from './types';
/**
* 基于内容复杂度的策略
* 根据源文件的复杂度动态调整"过时"判定标准
*/
export const ContentComplexityStrategy: LocalizationStrategy = {
name: 'content-complexity',
description: '根据内容复杂度调整翻译状态判定标准',
async calculateStatus(
source: FileInfo,
translation: FileInfo | null,
context: StrategyContext
) {
// 如果翻译不存在,返回缺失
if (!translation) {
return { status: 'missing', reason: 'Translation file not found' };
}
// 计算内容复杂度
const complexity = calculateComplexity(source.content);
// 根据复杂度确定天数阈值
const dayThreshold = getDayThreshold(complexity);
// 检查时间差
const sourceTime = source.lastModified.getTime();
const translationTime = translation.lastModified.getTime();
const daysDiff = (sourceTime - translationTime) / (1000 * 60 * 60 * 24);
if (daysDiff > dayThreshold) {
return {
status: 'outdated',
reason: `Source is ${daysDiff.toFixed(0)} days newer (threshold: ${dayThreshold})`,
complexity,
};
}
return {
status: 'done',
complexity,
};
},
async getPriority(source: FileInfo, translation: FileInfo | null) {
const complexity = calculateComplexity(source.content);
if (complexity > 0.8) return 'high';
if (complexity > 0.5) return 'medium';
return 'low';
},
};
/**
* 计算内容复杂度(0-1)
*/
function calculateComplexity(content: string): number {
const factors = {
// 代码块数量
codeBlocks: (content.match(/```/g) || []).length / 10,
// 链接数量
links: (content.match(/\[.*?\]\(.*?\)/g) || []).length / 20,
// 特殊语法
specialSyntax: (content.match(/\{.*?\}/g) || []).length / 30,
// 文件长度
length: content.length / 10000,
};
// 加权平均
return (
factors.codeBlocks * 0.3 +
factors.links * 0.2 +
factors.specialSyntax * 0.3 +
factors.length * 0.2
);
}
/**
* 根据复杂度获取天数阈值
*/
function getDayThreshold(complexity: number): number {
// 复杂度越高,阈值越大(给翻译者更多时间)
if (complexity > 0.8) return 30;
if (complexity > 0.5) return 14;
return 7;
}
注册自定义策略
// lunaria.config.ts
import { defineConfig } from '@lunariajs/core';
import { ContentComplexityStrategy } from './src/strategies/content-complexity';
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko'],
// 注册自定义策略
strategies: {
// 默认策略
default: 'git-timestamp',
// 按文件模式应用不同策略
rules: [
{
pattern: 'docs/guides/**/*.md',
strategy: 'content-complexity',
},
{
pattern: 'docs/api/**/*.md',
strategy: 'strict', // API 文档使用严格模式
},
{
pattern: '**/changelog.md',
strategy: 'lenient', // 变更日志使用宽松模式
},
],
// 注册自定义策略
custom: [ContentComplexityStrategy],
},
files: [
{
sourcePath: 'docs/{slug}.md',
localizationPath: 'i18n/{lang}/{slug}.md',
},
],
});
大型项目优化
性能瓶颈分析
大型项目的常见性能瓶颈:
| 瓶颈 | 原因 | 解决方案 |
|---|---|---|
| Git 操作过多 | 每个文件都查询 Git 历史 | 批量查询 Git 信息 |
| 文件 I/O 过多 | 逐个读取文件 | 并行读取 |
| 配置解析慢 | 复杂的 glob 模式 | 缓存 glob 结果 |
| 仪表板生成慢 | 大量模板渲染 | 增量渲染 |
增量构建策略
只处理变更的文件:
// lunaria.config.ts
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko'],
// 启用增量构建
incremental: {
enabled: true,
// 缓存目录
cacheDir: '.lunaria/cache',
// 缓存有效期(秒)
cacheTTL: 3600,
// 强制全量构建的条件
forceRebuild: {
// 配置文件变更时强制全量
configChanged: true,
// 添加新语言时强制全量
languageAdded: true,
},
},
files: [
{
sourcePath: 'docs/{slug}.md',
localizationPath: 'i18n/{lang}/{slug}.md',
},
],
});
并行处理
启用并行处理加速构建:
// lunaria.config.ts
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko'],
// 并行处理配置
parallel: {
enabled: true,
// 工作线程数量(默认为 CPU 核心数)
workers: 4,
// 每批处理的文件数量
batchSize: 100,
// 超时时间(毫秒)
timeout: 60000,
},
files: [
// ...
],
});
缓存机制
配置缓存以加速重复构建:
// lunaria.config.ts
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko'],
// 缓存配置
cache: {
// Git 信息缓存
git: {
enabled: true,
ttl: 86400, // 24 小时
},
// 文件内容缓存
content: {
enabled: true,
ttl: 3600, // 1 小时
},
// 状态计算缓存
status: {
enabled: true,
ttl: 3600, // 1 小时
},
},
files: [
// ...
],
});
安全与权限
敏感文件处理
排除敏感文件不被追踪:
// lunaria.config.ts
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko'],
files: [
{
sourcePath: 'docs/{slug}.md',
localizationPath: 'i18n/{lang}/{slug}.md',
// 排除敏感文件
exclude: [
'**/internal/**',
'**/.env*',
'**/secrets/**',
'**/admin/**',
],
},
],
// 全局排除规则
globalExclude: [
'**/node_modules/**',
'**/.git/**',
'**/dist/**',
'**/.env*',
'**/credentials*',
],
});
访问控制
为仪表板添加访问控制:
// lunaria.config.ts
export default defineConfig({
// ...其他配置
dashboard: {
outputDir: 'public/i18n-status',
title: 'Translation Status',
// 访问控制
accessControl: {
enabled: true,
// 基本认证
basicAuth: {
enabled: process.env.NODE_ENV === 'production',
username: process.env.I18N_DASHBOARD_USER,
password: process.env.I18N_DASHBOARD_PASS,
},
// IP 白名单
ipWhitelist: [
'192.168.1.0/24',
'10.0.0.0/8',
],
// 或使用自定义认证函数
customAuth: async (request) => {
const token = request.headers.get('Authorization');
return validateToken(token);
},
},
},
});
审计日志
启用审计日志记录:
// lunaria.config.ts
export default defineConfig({
// ...其他配置
// 审计日志
audit: {
enabled: true,
// 日志级别
level: 'info', // 'debug' | 'info' | 'warn' | 'error'
// 日志输出
outputs: [
{ type: 'file', path: 'logs/lunaria.log' },
{ type: 'console' },
],
// 记录的事件
events: [
'config.load',
'status.calculate',
'dashboard.generate',
'api.access',
],
},
});
与企业工具集成
翻译管理系统集成
与专业翻译管理平台集成:
// lunaria.config.ts
export default defineConfig({
// ...其他配置
// 集成配置
integrations: {
// Crowdin 集成
crowdin: {
enabled: true,
projectId: process.env.CROWDIN_PROJECT_ID,
apiToken: process.env.CROWDIN_API_TOKEN,
// 同步配置
sync: {
direction: 'bidirectional', // 'push' | 'pull' | 'bidirectional'
interval: 3600, // 同步间隔(秒)
},
},
// 或使用 Transifex
transifex: {
enabled: false,
organization: 'your-org',
project: 'your-project',
apiToken: process.env.TRANSIFEX_API_TOKEN,
},
},
});
CMS 集成
与内容管理系统集成:
// lunaria.config.ts
export default defineConfig({
// ...其他配置
integrations: {
// Contentful CMS
contentful: {
enabled: true,
spaceId: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
// 内容映射
contentMapping: {
'blogPost': 'posts/{slug}.md',
'documentation': 'docs/{slug}.md',
},
},
// 或使用 Strapi
strapi: {
enabled: false,
apiUrl: process.env.STRAPI_API_URL,
apiToken: process.env.STRAPI_API_TOKEN,
},
},
});
内部工具定制
为内部工具创建自定义适配器:
// src/adapters/internal-tool.ts
import { Adapter, FileInfo, TranslationStatus } from '@lunariajs/core';
/**
* 内部工具适配器
*/
export class InternalToolAdapter implements Adapter {
name = 'internal-tool';
constructor(private config: InternalToolConfig) {}
async syncTranslations(
files: FileInfo[],
statuses: TranslationStatus[]
): Promise<void> {
// 将状态同步到内部系统
const response = await fetch(`${this.config.apiUrl}/translations/sync`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiToken}`,
},
body: JSON.stringify({
files,
statuses,
timestamp: new Date().toISOString(),
}),
});
if (!response.ok) {
throw new Error(`Failed to sync: ${response.statusText}`);
}
}
async getTranslationAssignments(
file: FileInfo,
language: string
): Promise<Assignment[]> {
// 从内部系统获取翻译分配信息
const response = await fetch(
`${this.config.apiUrl}/assignments?file=${file.path}&lang=${language}`
);
return response.json();
}
}
实战案例:大型开源项目配置
Astro 官方文档案例分析
// Astro 官方文档的 LunariaJS 配置示例
import { defineConfig } from '@lunariajs/core';
export default defineConfig({
sourceLanguage: 'en',
languages: ['en', 'zh-cn', 'ja', 'ko', 'es', 'pt-br', 'de', 'fr'],
files: [
// 主要文档
{
sourcePath: 'src/content/docs/en/{slug}.md',
localizationPath: 'src/content/docs/{lang}/{slug}.md',
include: ['**/*.md', '**/*.mdx'],
exclude: ['**/reference/**'], // API 参考自动生成,不需要翻译
},
// 示例代码
{
sourcePath: 'examples/{slug}/README.md',
localizationPath: 'examples/{slug}/README.{lang}.md',
},
],
dashboard: {
outputDir: 'public/i18n-status',
title: 'Astro Docs Translation Status',
description: 'Track the progress of Astro documentation translations',
},
// 自定义状态规则
statusRules: {
outdated: {
dayThreshold: 14, // 14 天以上算过时
},
},
// 排除规则
globalExclude: [
'**/node_modules/**',
'**/.git/**',
'**/dist/**',
'**/CHANGELOG.md',
'**/CONTRIBUTING.md',
],
});
配置文件完整示例
// lunaria.config.ts - 企业级完整配置
import { defineConfig } from '@lunariajs/core';
import { ContentComplexityStrategy } from './strategies/content-complexity';
const isProduction = process.env.NODE_ENV === 'production';
const isCI = process.env.CI === 'true';
export default defineConfig({
// 基础配置
sourceLanguage: 'en',
languages: isProduction
? ['en', 'zh-cn', 'ja', 'ko', 'es', 'fr', 'de', 'pt-br']
: ['en', 'zh-cn'],
// 文件配置
files: [
{
sourcePath: 'src/content/docs/{slug}.mdx',
localizationPath: 'src/content/docs/{lang}/{slug}.mdx',
include: ['**/*.mdx'],
exclude: isCI ? ['**/draft/**', '**/internal/**'] : [],
group: 'docs',
},
{
sourcePath: 'src/content/blog/{slug}.md',
localizationPath: 'src/content/blog/{lang}/{slug}.md',
group: 'blog',
},
{
sourcePath: 'src/locales/en/{module}.json',
localizationPath: 'src/locales/{lang}/{module}.json',
group: 'ui',
},
],
// 状态规则
statusRules: {
outdated: { dayThreshold: 7 },
},
// 策略配置
strategies: {
default: 'git-timestamp',
rules: [
{ pattern: 'src/content/docs/**/*.mdx', strategy: 'content-complexity' },
],
custom: [ContentComplexityStrategy],
},
// 仪表板配置
dashboard: {
outputDir: isProduction ? 'dist/i18n-status' : 'public/i18n-status',
title: 'Enterprise Docs - Translation Status',
groupBy: 'group',
},
// 性能优化
incremental: { enabled: true },
parallel: { enabled: true, workers: 4 },
cache: {
git: { enabled: true, ttl: 86400 },
content: { enabled: true, ttl: 3600 },
},
// 安全配置
globalExclude: [
'**/node_modules/**',
'**/.git/**',
'**/dist/**',
'**/.env*',
'**/secrets/**',
],
// 审计日志
audit: {
enabled: isProduction,
level: 'info',
outputs: [{ type: 'file', path: 'logs/lunaria.log' }],
},
});
总结
本章探讨了 LunariaJS 的高级配置和企业级应用:
| 主题 | 关键内容 |
|---|---|
| 自定义状态规则 | 天数阈值、自定义检查函数 |
| 复杂路径映射 | 多文件模式、多源语言 |
| 多仓库管理 | Monorepo、跨仓库依赖 |
| 自定义策略 | 策略接口、实现、注册 |
| 性能优化 | 增量构建、并行处理、缓存 |
| 安全权限 | 敏感文件、访问控制、审计 |
| 企业集成 | TMS、CMS、内部工具 |
关键要点:
- 灵活运用条件配置适应不同环境
- 设计自定义策略满足特定业务需求
- 启用性能优化处理大规模文件
- 配置安全措施保护敏感信息
下一步
下一篇文章,我们将进行完整的企业级实战,从零构建一个完整的多语言文档平台,综合运用本系列所有知识点。
敬请期待!
💡 推荐阅读: