• 【国际化多语言方案】i18n / class google sheets v4 api 在线文档同步json


    国际化多语言方案 i18n / class google sheets v4 api 在线文档同步json


    前言


    提示:以下是本篇文章正文内容,下面案例可供参考

    一、参考链接

    这次用到的在线excel https://docs.google.com/spreadsheets/d/1A0Vf_qSWuGD-lY-mrktUwrWVWL9tdLMhoAFgY27bKtc/edit#gid=0

    文档:https://developers.google.com/sheets/api/reference/rest?apix=true
    创建应用:https://www.appsheet.com/home/apps

    二、使用步骤

    创建应用,生成密钥,启用API服务

    在这里插入图片描述
    在这里插入图片描述

    三、使用演示

    运行脚本 npm run lang

    在这里插入图片描述
    生成对应结构的对象
    在这里插入图片描述
    在线excel地址
    在这里插入图片描述

    在线json格式
    在这里插入图片描述
    在这里插入图片描述

    四、 代码

    excel 同步脚本代码

    类目合并多单元格之后 第一个位置上是空的,temp用于临时保存类目名称,listKey:组件名称, 这样子的好处就是{t(‘home.albums’)} 如此查阅代码可读性更好, 不同的组件带不同的组件名,excel也好对应查找,代码也是可读性更好。

    const https = require('https');
    const path = require('path');
    const fs = require('fs');
    const mkdirp = require('mkdirp');
    
    const spreadsheetId = '1A0Vf_qSWuGD-lY-mrktUwrWVWL9tdLMhoAFgY27bKtc';
    const apiKey = 'AIzaSyAdMMws4B9unzBrtAqORK0zM6oSi0BTadQ';
    const sheetName = 'share';
    
    const generateLanguage = (str) => {
      const data = JSON.parse(str).values;
      const langName = data.shift().slice(2); // 去掉首列
      const contentWebExt = {};
      const contentWebPage = {};
      langName.forEach((name) => {
        contentWebExt[name] = {};
        contentWebPage[name] = {};
      });
      let temp;
      data.forEach(([key, ...ts]) => {
        let listKey;
        if (key !== '') {
          // 类目合并多单元格之后 第一个位置上是空的,temp用于临时保存类目名称,listKey:组件名称
          temp = key;
          listKey = key;
        } else {
          listKey = temp;
        }
    
        langName.forEach((name, i) => {
          const message = ts[i + 1] || ts.find((e) => e);
          if (message) {
            const msg = message;
            contentWebExt[langName[i]][listKey] = {
              ...contentWebExt[name][temp],
              [ts[0]]: msg.replace(/^\w/, (w) => w.toUpperCase(w))
            };
          }
        });
      });
      langName.forEach((name) => {
        const p = path.resolve(__dirname, `../src/locales/${name}/translation.json`);
        mkdirp(path.dirname(p), (err) => {
          if (err) throw err;
          fs.writeFileSync(p, JSON.stringify(contentWebExt[name], null, 2));
        });
        // eslint-disable-next-line no-console
        console.log(`生成语言包:${name}`);
      });
    };
    
    const options = {
      hostname: 'sheets.googleapis.com',
      port: 443,
      path: `/v4/spreadsheets/${spreadsheetId}/values/${sheetName}?key=${apiKey}`,
      method: 'GET'
    };
    
    const req = https.request(options, (res) => {
      let str = '';
      res.setEncoding('utf8');
      res.on('data', (chunk) => {
        str += chunk;
      });
      res.on('end', () => {
        try {
          generateLanguage(str);
        } catch (e) {
          // eslint-disable-next-line no-console
          console.log(str, e);
        }
      });
    });
    
    req.on('error', (e) => {
      // eslint-disable-next-line no-console
      console.error(`problem with request: ${e.message}`);
    });
    
    req.end();
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    组件代码

    import React, { useState, useEffect } from 'react';
    import { useTranslation } from 'react-i18next';
    
    const Child = () => {
        const { t, i18n } = useTranslation();
        const [lang, setLang] = useState('zh');
    
        useEffect(() => {
            setLang(i18n.language);
        }, [i18n.language]);
    
        const handleChangeLang = (param) => {
            setLang(lang)
            i18n.changeLanguage(param)
            console.log(param, i18n.language);
        }
        
        const langList = ['zh', 'es', 'fr', 'en']
    
        return (
            
    { langList.map(i => { return ( ) })}

    {t('home.albums')}

    ) } export default Child;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    五、 另外一种实现代码

    通过调用Locale的静态方法来改变语言

    	// 用于组件源码demo语言包
    import ZhCNLang from './lang/zh';
    import EnUSLang from './lang/en';
    
    export const isObject = (val: unknown): val is Record => val !== null && typeof val === 'object';
    
    export const deepMerge = (target: any, newObj: any) => {
      Object.keys(newObj).forEach((key) => {
        let targetValue = target[key];
        let newObjValue = newObj[key];
        if (isObject(targetValue) && isObject(newObjValue)) {
          deepMerge(targetValue, newObjValue);
        } else {
          target[key] = newObjValue;
        }
      });
      return target;
    };
    
    // 组件默认语言设置
    export type Lang = Record;
    const langs: Lang = {
      'zh-CN': new ZhCNLang(),
      'en-US': new EnUSLang()
    };
    export class Locale {
      static currentLang = 'zh-CN';
      static languages(): Lang {
        return langs[this.currentLang];
      }
      static use(lang: string, newLanguages?: any) {
        if (newLanguages) {
          langs[lang] = new newLanguages();
        }
        this.currentLang = lang;
      }
      static merge(lang: string, newLanguages: any) {
        if (newLanguages) {
          if (langs[lang]) {
            deepMerge(langs[lang], newLanguages);
          } else {
            this.use(lang, newLanguages);
          }
        }
      }
    }
    export default Locale;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    同步在线文档的脚本只需要将json转为class就行了

    const getClass = function (a, obj) {
        const key = Object.keys(obj)
        let res = ''
        for (let i = 0; i < key.length; i++) {
          res += key[i] + "=" + JSON.stringify(obj[key])
        }
        return "class " + a + " {\n" + res + "\n} \n export default Lang;"
      };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    按文件类型自动分类文件的快速方法
    postman使用pre-request script
    免费数据 | 新库上线 | CnOpenData中国保险中介机构网点全集数据
    定期清理ES
    Vue3从零开始——掌握setup、ref和reactive函数的奥秘
    在使用tomcat运行项目时,遇到端口80被占用的情况问题解决
    Elasticsearch:运用 Python 实时通过 Logstash 写入日志到 Elasticsearch
    Java应用工程结构
    learnopengl 中 pbr的球体算法
    第十四届蓝桥杯(Web应用开发)模拟赛1期-大学组
  • 原文地址:https://blog.csdn.net/daddykei/article/details/125982892