mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
fix: flatten i18n keys (#2483)
This commit is contained in:
@@ -5,11 +5,15 @@ import path from 'node:path';
|
||||
import { format } from 'prettier';
|
||||
|
||||
import { getAllProjectLanguages, getRemoteTranslations } from './api.js';
|
||||
import type { TranslationRes } from './utils.js';
|
||||
import { flattenTranslation, type TranslationRes } from './utils.js';
|
||||
|
||||
const INDENT = 2;
|
||||
const RES_DIR = path.resolve(process.cwd(), 'src', 'resources');
|
||||
|
||||
const countKeys = (obj: TranslationRes) => {
|
||||
const countKeys = (obj: TranslationRes | null) => {
|
||||
if (!obj) {
|
||||
return 0;
|
||||
}
|
||||
let count = 0;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
Object.entries(obj).forEach(([_, value]) => {
|
||||
@@ -42,6 +46,12 @@ const getBaseTranslations = async (baseLanguage: { tag: string }) => {
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
try {
|
||||
fs.access(RES_DIR);
|
||||
} catch (error) {
|
||||
fs.mkdir(RES_DIR);
|
||||
console.log('Create directory', RES_DIR);
|
||||
}
|
||||
console.log('Loading project languages...');
|
||||
const languages = await getAllProjectLanguages();
|
||||
const baseLanguage = languages.find(language => language.base);
|
||||
@@ -58,11 +68,17 @@ const main = async () => {
|
||||
console.log(`Loading ${language.tag} translations...`);
|
||||
const translations = await getRemoteTranslations(language.tag);
|
||||
const keyNum = countKeys(translations);
|
||||
const completeRate = Number((keyNum / baseKeyNum).toFixed(3));
|
||||
console.log(
|
||||
`Load ${language.name} ${
|
||||
completeRate * 100
|
||||
}, %(${keyNum}/${baseKeyNum}) complete`
|
||||
);
|
||||
|
||||
return {
|
||||
...language,
|
||||
translations,
|
||||
completeRate: keyNum / baseKeyNum,
|
||||
completeRate,
|
||||
};
|
||||
})
|
||||
);
|
||||
@@ -81,10 +97,10 @@ const main = async () => {
|
||||
{
|
||||
'// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.':
|
||||
'',
|
||||
...language.translations,
|
||||
...flattenTranslation(language.translations),
|
||||
},
|
||||
null,
|
||||
4
|
||||
INDENT
|
||||
) + '\n'
|
||||
);
|
||||
});
|
||||
@@ -92,7 +108,7 @@ const main = async () => {
|
||||
console.log('Generating meta data...');
|
||||
const code = `// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
// Run \`yarn run download-resources\` to regenerate.
|
||||
// To overwrite this, please overwrite download.ts script.
|
||||
// If you need to update the code, please edit \`i18n/src/scripts/download.ts\` inside your project.
|
||||
${availableLanguages
|
||||
.map(
|
||||
language =>
|
||||
@@ -100,14 +116,16 @@ const main = async () => {
|
||||
language.tag
|
||||
}.json'`
|
||||
)
|
||||
.sort()
|
||||
.join('\n')}
|
||||
|
||||
export const LOCALES = [
|
||||
${availableLanguages
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- omit key
|
||||
.map(({ translations, ...language }) =>
|
||||
JSON.stringify({
|
||||
...language,
|
||||
// a trick to generate a string without quotation marks
|
||||
res: '__RES_PLACEHOLDER',
|
||||
}).replace(
|
||||
'"__RES_PLACEHOLDER"',
|
||||
@@ -124,7 +142,7 @@ const main = async () => {
|
||||
parser: 'typescript',
|
||||
singleQuote: true,
|
||||
trailingComma: 'es5',
|
||||
tabWidth: 4,
|
||||
tabWidth: INDENT,
|
||||
arrowParens: 'avoid',
|
||||
})
|
||||
);
|
||||
|
||||
@@ -1,3 +1,35 @@
|
||||
export interface TranslationRes {
|
||||
[x: string]: string | TranslationRes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively flattens a JSON object using dot notation.
|
||||
*
|
||||
* NOTE: input must be an object as described by JSON spec. Arbitrary
|
||||
* JS objects (e.g. {a: () => 42}) may result in unexpected output.
|
||||
* MOREOVER, it removes keys with empty objects/arrays as value (see
|
||||
* examples bellow).
|
||||
*
|
||||
* @example
|
||||
* flattenTranslation({a: 1, b: [{c: 2, d: {e: 3}}, 4]})
|
||||
* // {a: 1, b.0.c: 2, b.0.d.e: 3, b.1: 4}
|
||||
* flattenTranslation({a: 1, b: [{c: 2, d: {e: [true, false, {f: 1}]}}]})
|
||||
* // {a: 1, b.0.c: 2, b.0.d.e.0: true, b.0.d.e.1: false, b.0.d.e.2.f: 1}
|
||||
* flattenTranslation({a: 1, b: [], c: {}})
|
||||
* // {a: 1}
|
||||
*
|
||||
* @param obj item to be flattened
|
||||
*/
|
||||
export const flattenTranslation = (
|
||||
obj: string | TranslationRes,
|
||||
path?: string
|
||||
): TranslationRes => {
|
||||
if (!(obj instanceof Object)) return { [path ?? '']: obj };
|
||||
|
||||
return Object.keys(obj).reduce((output, key) => {
|
||||
return {
|
||||
...output,
|
||||
...flattenTranslation(obj[key], path ? path + '.' + key : key),
|
||||
};
|
||||
}, {});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user