目录
- 配置默认语言为中文
- 服务配置模块汉化
- 右侧描述汉化
- 结果展示
1. 配置默认语言为中文
修改i18nextUtil中的fallbackLng值,改为’zh-CN’
路径:OpenMetadata/openmetadata-ui/src/main/resources/ui/src/utils/i18next/i18nextUtil.ts
......
// Returns i18next options
export const getInitOptions = (): InitOptions => {
return {
supportedLngs: Object.values(SupportedLocales),
resources: {
'en-US': { translation: enUS },
'fr-FR': { translation: frFR },
'zh-CN': { translation: zhCN },
'ja-JP': { translation: jaJP },
'pt-BR': { translation: ptBR },
'pt-PT': { translation: ptPT },
'es-ES': { translation: esES },
'gl-ES': { translation: glES },
'ru-RU': { translation: ruRU },
'de-DE': { translation: deDe },
'he-HE': { translation: heHE },
'nl-NL': { translation: nlNL },
'pr-PR': { translation: prPR },
'th-TH': { translation: thTH },
'mr-IN': { translation: mrIN },
'ko-KR': { translation: koKR },
},
fallbackLng: ['zh-CN'],
detection: {
order: ['querystring', 'cookie', 'navigator'],
caches: ['cookie'], // cache user language on
},
interpolation: {
escapeValue: false, // XSS safety provided by React
},
missingKeyHandler: (_lngs, _ns, key) =>
// eslint-disable-next-line no-console
console.error(`i18next: key not found "${key}"`),
saveMissing: true, // Required for missing key handler
};
};
};
2. 服务配置模块汉化
2.1 字段提取与翻译
在locale下面新建一个zh-cn.json,将需要汉化的字段提取出来,分别写在zh-cn.json和en-us.json内,比如服务配置主要分布在OpenMetadata-main/openmetadata-spec/src/main/resources/json/schema/entity/services/connections下,例如
路径:OpenMetadata/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json
字段提取可以手动,也可以脚本提取,分享一个脚本json_title_extractor.js,在命令行运行
node json_title_extractor.js
不同页面需要更改目标目录地址targetDir
// json_title_extractor.js
const fs = require('fs');
const path = require('path');
****************第一种***************
// 定义目标目录
const targetDir = path.join(__dirname, 'openmetadata-spec', 'src', 'main', 'resources', 'json', 'schema', 'entity', 'services', 'connections', 'database');
// 读取目录下的所有文件
fs.readdir(targetDir, (err, files) => {
if (err) {
console.error('读取目录时出错:', err);
return;
}
// 过滤出所有的 JSON 文件
const jsonFiles = files.filter(file => path.extname(file) === '.json');
const allTitles = {};
// 遍历每个 JSON 文件
jsonFiles.forEach(file => {
const filePath = path.join(targetDir, file);
try {
// 读取文件内容
const data = fs.readFileSync(filePath, 'utf8');
const jsonData = JSON.parse(data);
// 递归查找所有的 title 字段
function findTitles(obj) {
if (typeof obj === 'object' && obj!== null) {
if (obj.hasOwnProperty('title')) {
const title = obj.title;
allTitles[title] = title;
}
for (const key in obj) {
findTitles(obj[key]);
}
}
}
findTitles(jsonData);
} catch (error) {
console.error(`处理文件 ${file} 时出错:`, error);
}
});
// 格式化输出结果,为键和值添加双引号
const formattedOutput = Object.entries(allTitles).map(([key, value]) => {
return `"${key}": "${value}"`;
}).join(',\n');
console.log(formattedOutput);
});
*********************第二种**********************
//或者直接复制绝对地址文件地址
const targetFile = ' *****/OpenMetadata/openmetadata-ui/src/main/resources/ui/src/jsons/connectionSchemas/connections/serviceConnection.json';
try {
// 读取文件内容
const data = fs.readFileSync(targetFile, 'utf8');
const jsonData = JSON.parse(data);
const allTitles = {};
// 递归查找所有的 title 字段
function findTitles(obj) {
if (typeof obj === 'object' && obj!== null) {
if (obj.hasOwnProperty('title')) {
const title = obj.title;
// 转换为小写和短中划线格式
const kebabCaseKey = title
.replace(/([a-z0-9])([A-Z])/g, '$1-$2') // 处理驼峰命名
.replace(/[\s_]+/g, '-') // 替换空格和下划线
.toLowerCase();
allTitles[kebabCaseKey] = title;
}
for (const key in obj) {
findTitles(obj[key]);
}
}
}
findTitles(jsonData);
// 格式化输出结果
const formattedOutput = Object.entries(allTitles).map(([key, value]) => {
return `"${key}": "${value}"`;
}).join(',\n');
console.log(formattedOutput);
} catch (error) {
console.error(`处理文件时出错:`, error);
}
需要注意zh-cn.json的字段需要和en-us.json字段同步,不然会被程序自动删除
2.2 Form表单title渲染适配
在ConnectionConfigForm.tsx中,配置Form的国际化配置。声明一个函数translateSchemaTitles,将title进行多语言翻译,FormBuilder中schema调用translateSchemaTitles(connSch.schema, t)
路径:OpenMetadata/openmetadata-ui/src/main/resources/ui/src/components/Settings/Services/ServiceConfig/ConnectionConfigForm.tsx
type Schema = Record<string, any>;
// 将 title 转为进行多语言翻译
const translateSchemaTitles = (
schema: Schema,
t: (key: string) => string
): Schema => {
if (typeof schema !== 'object' || schema === null) {
return schema;
}
if (Array.isArray(schema)) {
return schema.map((item) => translateSchemaTitles(item, t));
}
const translated: Schema = { ...schema };
for (const key in translated) {
if (Object.prototype.hasOwnProperty.call(translated, key)) {
if (key === 'title') {
translated[key] = t(translated[key] as string) || translated[key];
} else if (key === 'properties' || key === 'definitions') {
const properties = translated[key];
for (const propKey in properties) {
if (Object.prototype.hasOwnProperty.call(properties, propKey)) {
properties[propKey] = translateSchemaTitles(
properties[propKey],
t
);
}
}
translated[key] = properties;
} else if (key === 'items' || key === 'additionalProperties') {
translated[key] = translateSchemaTitles(translated[key], t);
} else if (['allOf', 'anyOf', 'oneOf', 'not'].includes(key)) {
translated[key] = translateSchemaTitles(translated[key], t);
}
}
}
return translated;
};
return (
<FormBuilder
cancelText={cancelText}
formData={validConfig}
okText={okText}
ref={formRef}
schema={translateSchemaTitles(connSch.schema, t)}
serviceCategory={serviceCategory}
status={status}
uiSchema={connSch.uiSchema}
validator={validator}
onCancel={onCancel}
onFocus={onFocus}
onSubmit={handleSave}>
......
3. 右侧描述汉化
新建一个zh-CN文件夹,复制en-US中问内容,将文件中的title进行汉化
路径:OpenMetadata/openmetadata-ui/src/main/resources/ui/public/locales/zh-CN/Database
![目录结构](https://i-blog.csdnimg.cn/direct/5286c0c622aa40638cb2fb6f74d8244c.png