【国际化多语言方案】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();

组件代码

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 (
        <div>
           { langList.map(i => {
              return (
                <button onClick={() => handleChangeLang(i)}>hello {i}</button>
              )
            })}

            <p>{t('home.albums')}</p>
            
        </div>
    )
}
export default Child;

五、 另外一种实现代码

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

	// 用于组件源码demo语言包
import ZhCNLang from './lang/zh';
import EnUSLang from './lang/en';

export const isObject = (val: unknown): val is Record<any, any> => 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<string, any>;
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;

同步在线文档的脚本只需要将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;"
  };
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值