mdLoader.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /**
  2. * 按页面类型与语言动态加载 Markdown 文案(如服务条款、隐私政策)
  3. */
  4. type MdPageType = 'termsOfService' | 'privacyPolicy';
  5. const DEFAULT_LANG = 'en-US';
  6. // 匹配 @/assets/md/{pageName}_{lang}.md,如 termsOfService_en-US.md、privacyPolicy_zh-CN.md
  7. const rawMdModules = import.meta.glob<string>('@/assets/md/*_*.md', {
  8. query: '?raw',
  9. import: 'default',
  10. });
  11. const mdLoaders: Record<string, Record<string, () => Promise<string>>> = {};
  12. Object.keys(rawMdModules).forEach((key) => {
  13. const match = key.match(/\/([^/]+)_([\w-]+)\.md$/);
  14. if (match) {
  15. const [, pageName, lang] = match;
  16. if (!mdLoaders[pageName!]) mdLoaders[pageName!] = {};
  17. mdLoaders[pageName!]![lang!] = () => (rawMdModules[key] as () => Promise<string>)();
  18. }
  19. });
  20. const localeModules = import.meta.glob<{ default?: { DIR?: string } }>('@/locales/*.ts', {
  21. eager: true,
  22. });
  23. const dirByLang: Record<string, 'ltr' | 'rtl'> = {};
  24. Object.keys(localeModules).forEach((key) => {
  25. const match = key.match(/\/([\w-]+)\.ts$/);
  26. if (match) {
  27. const lang = match[1]!;
  28. const dir = localeModules[key]?.default?.DIR;
  29. if (dir === 'ltr' || dir === 'rtl') dirByLang[lang] = dir;
  30. }
  31. });
  32. export interface LoadMdByLangOptions {
  33. /** 占位符替换:key 为 MD 中的占位符(如 [Insert Date]),value 为替换后的字符串 */
  34. replacements?: Record<string, string>;
  35. }
  36. /**
  37. * 根据当前语言加载 Markdown 内容;无该语言时回退到英文。返回内容及实际使用的语言。
  38. * 可通过 options.replacements 替换 MD 中的占位符(如 [Insert Date])。
  39. */
  40. export async function loadMdByLang(
  41. page: MdPageType,
  42. lang: string,
  43. options?: LoadMdByLangOptions
  44. ): Promise<{ content: string; usedLang: string }> {
  45. const loaders = mdLoaders[page];
  46. const hasLang = Boolean(loaders?.[lang]);
  47. const usedLang = hasLang ? lang : DEFAULT_LANG;
  48. const loader = loaders?.[usedLang] ?? loaders?.[DEFAULT_LANG];
  49. if (!loader) return { content: '', usedLang };
  50. let content = await loader();
  51. const replacements = options?.replacements;
  52. if (replacements && Object.keys(replacements).length > 0) {
  53. content = Object.entries(replacements).reduce(
  54. (acc, [placeholder, value]) => acc.replaceAll(placeholder, value),
  55. content
  56. );
  57. }
  58. return { content, usedLang };
  59. }
  60. /**
  61. * 根据语言获取文案方向(ltr/rtl),用于 dir 与样式
  62. */
  63. export function getDirByLang(lang: string): 'ltr' | 'rtl' {
  64. return dirByLang[lang] ?? 'ltr';
  65. }
  66. export type { MdPageType };