Przeglądaj źródła

添加 i18n 多语言功能 (简易实现 适用于 wxml)

cc12458 3 miesięcy temu
rodzic
commit
364b5a03d3

+ 2 - 3
miniprogram/app.config.ts

@@ -2,18 +2,17 @@ import { getAccountInfoSync } from "./lib/wx/open-api";
 
 const miniProgram = getAccountInfoSync();
 const env = miniProgram.envVersion;
-console.log("env",env)
 let host = "wx2.hzliuzhi.com";
 if (env === "trial") {
   host = "test.hzliuzhi.com";
 } else if (env === "develop") {
-  // host = "wx2.hzliuzhi.com";
   host = "wx.hzliuzhi.com:4433";
-  // host = "test.hzliuzhi.com";
 }
 console.log("host",host)
 export const HOST = host;
 export const Base_URL = `https://${host}/manager/fdhb-mobile`;
 export const Upload_URL = `https://${host}/manager/file`;
+export const Locale_URL = `https://${host}/admin/i18n`
+export const ENV = env;
 
 

+ 3 - 1
miniprogram/app.ts

@@ -1,7 +1,7 @@
 import { login } from "./lib/logic";
 import { appUpdate } from "./lib/wx/update";
 import { useRouteQuery } from "./utils/route-query";
-// import { Get } from "./lib/request/method";
+import i18n from "./i18n/install";
 
 // app.ts
 App<IAppOption>({
@@ -10,7 +10,9 @@ App<IAppOption>({
     patientId: "",
     dictionaries: [],
   },
+  i18n: null,
   onLaunch(options: WechatMiniprogram.App.LaunchShowOption) {
+    i18n().then((value) => this.i18n = value);
     appUpdate(true);
     const scene = options.query.scene;
     const query = useRouteQuery(scene);

+ 24 - 0
miniprogram/i18n/behavior.ts

@@ -0,0 +1,24 @@
+import request from './install';
+import { PREFIX, formatRecord, formatData } from './tool';
+export default Behavior({
+  lifetimes: {
+    created() { this._i18n_init(false); },
+  },
+  pageLifetimes: {
+    created() { this._i18n_init(true); },
+  },
+  methods: {
+    async _i18n_init(page?: boolean) {
+      const [gather, reset] = formatRecord(this.data[PREFIX]);
+      const app = getApp({ allowDefault: true });
+      if (app.i18n == null) {
+        if (reset) this.setData(reset);
+        app.i18n = await request();
+      }
+      if (app.i18n != null) {
+        const i18n = formatData(gather, (key) => app.i18n?.[key]);
+        if (i18n) this.setData(i18n);
+      } else this.setData(formatData(gather));
+    },
+  }
+});

+ 15 - 0
miniprogram/i18n/install.ts

@@ -0,0 +1,15 @@
+import { Locale_URL, ENV } from '../app.config';
+import { Get } from '../lib/request/method';
+
+import { flatRecordKeys } from './tool';
+
+let cache = null;
+
+export default async function request(url?: string) {
+  try {
+    const { locales } = await Get(url ?? `${Locale_URL}/applet.${ENV}.json`, { notTransform: true, shareRequest: true });
+    return cache = flatRecordKeys(locales), cache;
+  } catch (error) {
+    return null;
+  }
+}

+ 45 - 0
miniprogram/i18n/tool.ts

@@ -0,0 +1,45 @@
+export const PREFIX = 'i18n';
+export function flatRecordKeys(
+  record: Record<string, any>,
+  parent: string[] = [],
+  result: Record<string, string> = {}
+) {
+  if (record && typeof record === 'object') {
+    for (const [key, value] of Object.entries(record)) {
+      if (Array.isArray(value)) value.forEach((v, i) => {
+        const keys = [...parent, `${key}[${i}]`];
+        flatRecordKeys(v, keys, result);
+      }); else {
+        const keys = [...parent, key];
+        flatRecordKeys(value, keys, result);
+      }
+    }
+  } else if (['string', 'boolean', 'number'].includes(typeof record)) result[parent.join('.')] = record;
+  return result;
+}
+
+type FormatData = { key: string; value: string; }[];
+
+export function formatRecord(record: Record<string, any> | string[]) {
+  if (Array.isArray(record)) return [record.map(key => ({ key, value: '' })), null] as const;
+
+  let reset: FormatData = [];
+  const gather: FormatData = [];
+
+  const result = flatRecordKeys(record);
+  for (let [key, value] of Object.entries(result)) {
+    if (typeof value === 'string') {
+      value = value?.replace(/^_/, '').replace(/\\_/, '_') ?? ''
+      if (value) reset.push({ key, value });
+    }
+    gather.push({ key, value });
+  }
+  return [gather, formatData(reset)] as const;
+}
+
+export function formatData(data?: FormatData, get?: (key: string) => string) {
+  return data?.reduce((set, { key, value }) => {
+    const _key = PREFIX ? `${PREFIX}.${key}` : key;
+    return (set[_key] = get?.(key) ?? value ?? '', set);
+  }, {} as Record<string, string>) ?? null;
+}

+ 3 - 1
miniprogram/lib/request/create.ts

@@ -4,8 +4,8 @@ import { getAccountInfoSync } from "../wx/open-api";
 
 const shareRequestCache = new Map<string, IRequestData<any>>();
 
-const miniProgram = getAccountInfoSync();
 
+const miniProgram = getAccountInfoSync();
 export function createRequest(option: IRequestCreateConfig) {
   const { baseURL } = option;
 
@@ -16,6 +16,7 @@ export function createRequest(option: IRequestCreateConfig) {
       params,
       header,
       meta,
+      notTransform = false,
       transform = (params: any) => params,
       shareRequest,
       ..._config
@@ -55,6 +56,7 @@ export function createRequest(option: IRequestCreateConfig) {
       ..._config,
     }).then((response) => {
       if (response.statusCode === 200) {
+        if (notTransform) return response.data;
         if (response.data.code === 200 && response.data.success !== false) {
           const data =
             Array.isArray(response.data.rows) && response.data.total != null

+ 1 - 0
typings/app/request.d.ts

@@ -12,6 +12,7 @@ interface IRequestConfig<R, T> {
   timeout?: number;
   meta?: { ignoreToken: boolean };
   shareRequest?: boolean;
+  notTransform?: boolean;
   transform?: ({ data, header }: { data: T, header: Record<string, string> }) => R;
 }
 

+ 2 - 1
typings/index.d.ts

@@ -6,6 +6,7 @@ interface IAppOption {
     dictionaries: App.Dictionary[],
     patientId?: string;
     doctorId?: string;
-  }
+  };
+  i18n: Record<string, string> | null;
 }