玩一玩 Flutter 翻译项目, 用来学英语

April 24, 2019

需求

需要学一学 flutter 的东西, 发现中文文档翻译的挺好的: https://flutter-io.cn/docs

单击中文字的时候, 会在下方显示对应的英文.

正好可以拿来学习下英语, 不过我想要的效果是默认显示英文, 单击以后显示中文翻译.

搭建

找到了对应的翻译项目: https://github.com/cfug/flutter.cn.git

别完全按照 README 会有问题;

先 clone 下来, 并取下 submodule

git clone https://github.com/cfug/flutter.cn.git
cd flutter.cn
git submodule update --init --remote

然后安装

source ./tool/env-set.sh   # initialize environment variables; install/use required Node & Ruby version
./tool/before-install.sh   # install core set of required tools
./tool/install.sh   # install everything else needed to build this site

注意这里不能用 zsh, zsh 下 env-set.sh 无法正确生效, 导致后面的 before-install.sh 报: travis_fold:command not found 折腾了我很久, 得切换到 bash 下来装

漫长的安装 ruby flutter sdk 等等各种东西都装了一遍, 简直了

./tool/serve.sh

启动起来, 访问 http://localhost:4002 应该能看到页面了, 如果报错, 那么等待一段时间, 可能是因为还在编译 html

看到的内容和 https://flutter-io.cn/docs 不一样, 英文在上, 中文在下, 而且不存在什么点击然后显示的特性

仔细研究网页, 根据关键词搜索, 发现点击的 js 和处理隐藏的 css 来自于 ./tool/translator 这个项目, 进去大致看了下, 猜测就是用来实现那个特性的东西.

执行 ./tool/translator/build.sh , 注意要在项目目录执行, 脚本里都是相对路径.

又是各种漫长的等待, 然后看到了各种 inject, 没跑了, 就是这货

执行的时候, 注意把刚才的 http://localhost:4002 服务开着别动, 再次访问, 页面乱了, 发现因为找不到需要的 css

真是不靠谱啊, 手工拷贝过去:

cd /Users/bigzhu/git/flutter.cn/_site/assets
cp -r ../../tool/translator/assets/translator ./

现在和在线网站感觉是一样的了, 单击显示英文

修改

尝试修改为默认英文, 单击显示中文

比较 inject 前后的 html , 中英文的对应的 p 位置还真交换了, 不是用 css 实现的. 我有点蒙.

找了半天, 这个项目里基本没啥东西. 发现了脚本里的 npm i -g @awesome-fe/[email protected]

顺藤摸瓜, 找到项目: https://github.com/asnowwolf/translate

取下来研究了一下, 哎

  export function markAndSwap(element: Element, selector: string): void {
    const elements = element.querySelectorAll(selector);
    elements.forEach(element => {
      if (containsChinese(element.innerHTML)) {
        const prev = element.previousElementSibling!;
        if (isPaired(prev, element) && !containsChinese(prev.innerHTML)) {
          element.setAttribute('translation-result', 'on');
          prev.setAttribute('translation-origin', 'off');
          element.parentElement!.insertBefore(element, prev);
          // 交换 id,中文内容应该占用原文的 id
          const id = prev.getAttribute('id');
          if (id) {
            prev.removeAttribute('id');
            element.setAttribute('id', id);
          }
          const href = prev.getAttribute('href');
          if (href) {
            element.setAttribute('href', href);
          }
          if (element.tagName.match(/(H[1-6]|li)/)) {
            const prevAnchor = prev.querySelector('a[href]');
            const thisAnchor = element.querySelector('a[href]');
            if (prevAnchor && thisAnchor && containsChinese(decodeURIComponent(thisAnchor.getAttribute('href')!)!)) {
              thisAnchor.setAttribute('href', prevAnchor.getAttribute('href')!);
            }
          }
        }
      }
    });
  }

真是出乎人意料的简单粗暴啊, 还真去交换了中英文的翻译内容的位置

改为如下:

  export function markAndSwap(element: Element, selector: string): void {
    const elements = element.querySelectorAll(selector);
    elements.forEach(element => {
      if (containsChinese(element.innerHTML)) {
        const prev = element.previousElementSibling!;
        if (isPaired(prev, element) && !containsChinese(prev.innerHTML)) {
          element.setAttribute('translation-result', 'off');
          prev.setAttribute('translation-origin', 'on');
          // 不要交换位置
          // element.parentElement!.insertBefore(element, prev);
          // 交换 id,中文内容应该占用原文的 id
          /*
          const id = prev.getAttribute('id');
          if (id) {
            prev.removeAttribute('id');
            element.setAttribute('id', id);
          }
           */
          const href = prev.getAttribute('href');
          if (href) {
            element.setAttribute('href', href);
          }
          if (element.tagName.match(/(H[1-6]|li)/)) {
            const prevAnchor = prev.querySelector('a[href]');
            const thisAnchor = element.querySelector('a[href]');
            if (prevAnchor && thisAnchor && containsChinese(decodeURIComponent(thisAnchor.getAttribute('href')!)!)) {
              thisAnchor.setAttribute('href', prevAnchor.getAttribute('href')!);
            }
          }
        }
      }
    });
  }

修改的代码放在我 fork 的项目里: bigzhu/translate

修改 build.sh:

#!/usr/bin/env bash

set -x
set -e

bundle exec jekyll build

cp -r tool/translator/assets/*  _site/assets/

npm i -g https://github.com/bigzhu/translate

nt inject '_site/**/*.html' -c /assets/translator/css/translator.css -s /assets/translator/js/translator.js -m ./tool/translator/url-map.json -t ./tool/translator/text-map.json

nt mark '_site/**/*.html'

npm 改为安装我修改后的项目

停止 ./tool/serve.sh 运行 npm run clean, 再次启动 ./tool/serve.sh, 重新生成修改前的 html

而后自然是执行 ./tool/translator/build.sh, inject 后访问, 依然是报对应的 js 和 css 找不到

cp 过去以后, 修改 translator.js 和 translator.css, 把 translation-origin 和 translation-result 交换一下就好了.

再次访问, 效果完美.

因为过程实在太麻烦了, 我干脆把编译好的网站传到了我的网站上: https://flutter.bigzhu.net

如果有不妥请联系我删除.


comments powered by Disqus