mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-11 18:41:47 +00:00
feat(i18n): i18n auto-importer
This commit is contained in:
@ -9,6 +9,7 @@ import { pluginVirtualModuleGenerator } from './vite-plugins/plugin-importer';
|
|||||||
import pluginLoader from './vite-plugins/plugin-loader';
|
import pluginLoader from './vite-plugins/plugin-loader';
|
||||||
|
|
||||||
import type { UserConfig } from 'vite';
|
import type { UserConfig } from 'vite';
|
||||||
|
import { i18nImporter } from './vite-plugins/i18n-importer';
|
||||||
|
|
||||||
const resolveAlias = {
|
const resolveAlias = {
|
||||||
'@': resolve(__dirname, './src'),
|
'@': resolve(__dirname, './src'),
|
||||||
@ -21,6 +22,7 @@ export default defineConfig({
|
|||||||
plugins: [
|
plugins: [
|
||||||
pluginLoader('backend'),
|
pluginLoader('backend'),
|
||||||
viteResolve({
|
viteResolve({
|
||||||
|
'virtual:i18n': i18nImporter(),
|
||||||
'virtual:plugins': pluginVirtualModuleGenerator('main'),
|
'virtual:plugins': pluginVirtualModuleGenerator('main'),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -65,6 +67,7 @@ export default defineConfig({
|
|||||||
plugins: [
|
plugins: [
|
||||||
pluginLoader('preload'),
|
pluginLoader('preload'),
|
||||||
viteResolve({
|
viteResolve({
|
||||||
|
'virtual:i18n': i18nImporter(),
|
||||||
'virtual:plugins': pluginVirtualModuleGenerator('preload'),
|
'virtual:plugins': pluginVirtualModuleGenerator('preload'),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -108,6 +111,7 @@ export default defineConfig({
|
|||||||
plugins: [
|
plugins: [
|
||||||
pluginLoader('renderer'),
|
pluginLoader('renderer'),
|
||||||
viteResolve({
|
viteResolve({
|
||||||
|
'virtual:i18n': i18nImporter(),
|
||||||
'virtual:plugins': pluginVirtualModuleGenerator('renderer'),
|
'virtual:plugins': pluginVirtualModuleGenerator('renderer'),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import i18next, { init, t as i18t, changeLanguage } from 'i18next';
|
import i18next, { init, t as i18t, changeLanguage } from 'i18next';
|
||||||
|
|
||||||
import { languageResources } from '@/i18n/resources';
|
import { languageResources } from 'virtual:i18n';
|
||||||
|
|
||||||
export const loadI18n = async () =>
|
export const loadI18n = async () =>
|
||||||
await init({
|
await init({
|
||||||
|
|||||||
11
src/i18n/resources/@types/index.ts
Normal file
11
src/i18n/resources/@types/index.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export interface LanguageResources {
|
||||||
|
[lang: string]: {
|
||||||
|
translation: Record<string, unknown> & {
|
||||||
|
language: {
|
||||||
|
name: string;
|
||||||
|
'local-name': string;
|
||||||
|
code: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import enJson from './en.json';
|
|
||||||
import koJson from './ko.json';
|
|
||||||
|
|
||||||
export const languageResources = {
|
|
||||||
en: {
|
|
||||||
translation: enJson
|
|
||||||
},
|
|
||||||
ko: {
|
|
||||||
translation: koJson
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -26,6 +26,8 @@ import { deepEqual } from 'fast-equals';
|
|||||||
|
|
||||||
import { allPlugins, mainPlugins } from 'virtual:plugins';
|
import { allPlugins, mainPlugins } from 'virtual:plugins';
|
||||||
|
|
||||||
|
import { languageResources } from 'virtual:i18n';
|
||||||
|
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
|
|
||||||
import { refreshMenu, setApplicationMenu } from '@/menu';
|
import { refreshMenu, setApplicationMenu } from '@/menu';
|
||||||
@ -52,8 +54,6 @@ import {
|
|||||||
import { LoggerPrefix } from '@/utils';
|
import { LoggerPrefix } from '@/utils';
|
||||||
import { loadI18n, setLanguage, t } from '@/i18n';
|
import { loadI18n, setLanguage, t } from '@/i18n';
|
||||||
|
|
||||||
import { languageResources } from '@/i18n/resources';
|
|
||||||
|
|
||||||
import type { PluginConfig } from '@/types/plugins';
|
import type { PluginConfig } from '@/types/plugins';
|
||||||
|
|
||||||
// Catch errors and log them
|
// Catch errors and log them
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import prompt from 'custom-electron-prompt';
|
|||||||
|
|
||||||
import { allPlugins } from 'virtual:plugins';
|
import { allPlugins } from 'virtual:plugins';
|
||||||
|
|
||||||
|
import { languageResources } from 'virtual:i18n';
|
||||||
|
|
||||||
import config from './config';
|
import config from './config';
|
||||||
|
|
||||||
import { restart } from './providers/app-controls';
|
import { restart } from './providers/app-controls';
|
||||||
@ -19,7 +21,7 @@ import promptOptions from './providers/prompt-options';
|
|||||||
|
|
||||||
import { getAllMenuTemplate, loadAllMenuPlugins } from './loader/menu';
|
import { getAllMenuTemplate, loadAllMenuPlugins } from './loader/menu';
|
||||||
import { setLanguage, t } from '@/i18n';
|
import { setLanguage, t } from '@/i18n';
|
||||||
import { languageResources } from '@/i18n/resources';
|
|
||||||
|
|
||||||
export type MenuTemplate = Electron.MenuItemConstructorOptions[];
|
export type MenuTemplate = Electron.MenuItemConstructorOptions[];
|
||||||
|
|
||||||
@ -104,7 +106,7 @@ export const mainMenuTemplate = async (
|
|||||||
return pluginEnabledMenu(id, pluginLabel, true, innerRefreshMenu);
|
return pluginEnabledMenu(id, pluginLabel, true, innerRefreshMenu);
|
||||||
});
|
});
|
||||||
|
|
||||||
const availableLanguages = Object.keys(languageResources) as unknown as (keyof typeof languageResources)[];
|
const availableLanguages = Object.keys(languageResources);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
|||||||
6
src/virtual-module.d.ts
vendored
6
src/virtual-module.d.ts
vendored
@ -12,3 +12,9 @@ declare module 'virtual:plugins' {
|
|||||||
Omit<Plugin, 'backend' | 'preload' | 'renderer'>
|
Omit<Plugin, 'backend' | 'preload' | 'renderer'>
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module 'virtual:i18n' {
|
||||||
|
import type { LanguageResources } from '@/i18n/resources/@types';
|
||||||
|
|
||||||
|
export const languageResources: LanguageResources;
|
||||||
|
}
|
||||||
|
|||||||
47
vite-plugins/i18n-importer.ts
Normal file
47
vite-plugins/i18n-importer.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { basename, relative, resolve, extname } from 'node:path';
|
||||||
|
|
||||||
|
import { globSync } from 'glob';
|
||||||
|
import { Project } from 'ts-morph';
|
||||||
|
|
||||||
|
const snakeToCamel = (text: string) =>
|
||||||
|
text.replace(/-(\w)/g, (_, letter: string) => letter.toUpperCase());
|
||||||
|
|
||||||
|
export const i18nImporter = () => {
|
||||||
|
const project = new Project({
|
||||||
|
tsConfigFilePath: resolve(__dirname, '..', 'tsconfig.json'),
|
||||||
|
skipAddingFilesFromTsConfig: true,
|
||||||
|
skipLoadingLibFiles: true,
|
||||||
|
skipFileDependencyResolution: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const srcPath = resolve(__dirname, '..', 'src');
|
||||||
|
const plugins = globSync([
|
||||||
|
'src/i18n/resources/*.json',
|
||||||
|
]).map((path) => {
|
||||||
|
const nameWithExt = basename(path);
|
||||||
|
const name = nameWithExt.replace(extname(nameWithExt), '');
|
||||||
|
|
||||||
|
return { name, path };
|
||||||
|
});
|
||||||
|
|
||||||
|
const src = project.createSourceFile('vm:i18n', (writer) => {
|
||||||
|
// prettier-ignore
|
||||||
|
for (const { name, path } of plugins) {
|
||||||
|
const relativePath = relative(resolve(srcPath, '..'), path).replace(/\\/g, '/');
|
||||||
|
writer.writeLine(`import ${snakeToCamel(name)}Json from "./${relativePath}";`);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.blankLine();
|
||||||
|
|
||||||
|
writer.writeLine('export const languageResources = {');
|
||||||
|
for (const { name } of plugins) {
|
||||||
|
writer.writeLine(` "${name}": {`);
|
||||||
|
writer.writeLine(` translation: ${snakeToCamel(name)}Json,`);
|
||||||
|
writer.writeLine(' },');
|
||||||
|
}
|
||||||
|
writer.writeLine('};');
|
||||||
|
writer.blankLine();
|
||||||
|
});
|
||||||
|
|
||||||
|
return src.getText();
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user