自动化翻译ceph文档

需求很简单,翻译官网的操作文档

下载ceph代码luminous版本

这个只用来编译doc的,我们只需要最新的这个分支即可,拉最少的代码

1
2
3
git clone -b v12.2.13 --single-branch --depth 1  git://github.com/ceph/ceph.git ceph12
cd ceph12
git checkout -b v12.2.13

代码就下好了

根据官网的文档可以知道,官网的文档的语法是Sphinx写的文档,然后通过工具可以渲染成固定的网页

https://docs.ceph.com/docs/luminous/dev/generatedocs/

而Sphinx写的文档是支持国际化的,也就是我们只需要通过固定的文件去修改翻译文本就可以实现整个文档的翻译,而翻译的过程是可以通过发送到google,然后拿到结果再填写回去的方式来处理

安装依赖包

1
2
cd admin
./build-doc

根据提示安装依赖包,有一个ditaa安装不上

1
2
3
4
wget ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora-secondary/releases/20/Everything/ppc64/os/Packages/d/ditaa-0.9-10.r74.fc20.noarch.rpm
wget https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/20/Everything/x86_64/os/Packages/j/jericho-html-3.2-6.fc20.noarch.rpm
rpm -ivh jericho-html-3.2-6.fc20.noarch.rpm
yum localinstall ditaa-0.9-10.r74.fc20.noarch.rpm

修改build-doc脚本的60行
virtualenv修改为

1
virtualenv-3

生成的文档在

1
[root@lab101 admin]# ls ../build-doc/output/html/

执行

1
./serve-doc

访问主机的8080端口

就可以看到一个原版的文档了

我们把这个备份下,方便后面比对翻译的效果

1
2
3
[root@lab101 admin]# unalias cp
[root@lab101 admin]# cp -ra ../build-doc/output/html/* /usr/share/nginx/html/
[root@lab101 admin]# systemctl start nginx

脚本里面还有其它的一些操作,实际上主要的编译命令是这个命令

1
/root/ceph/ceph12/build-doc/virtualenv/bin/sphinx-build -a -b dirhtml -d doctrees /root/ceph/ceph12/doc /root/ceph/ceph12/build-doc/output/html

我们的版本

1
2
[root@lab101 admin]# /root/ceph/ceph12/build-doc/virtualenv/bin/sphinx-build  --version
sphinx-build 2.1.2

安装国际化的处理软件

1
/root/ceph/ceph12/build-doc/virtualenv/bin/pip3 install sphinx-intl

提取pot文件

1
/root/ceph/ceph12/build-doc/virtualenv/bin/sphinx-build -b gettext /root/ceph/ceph12/doc locale

根据pot文件生成zh的po文件

1
/root/ceph/ceph12/build-doc/virtualenv/bin/sphinx-intl update -p locale/ -l zh

然后需要修改翻译就修改po文件

会在本地生成locales文件夹,把文件夹拷贝到doc目录下面

修改doc/conf.py文件

添加三个设置配置

1
2
3
locale_dirs = ['locales/']
gettext_compact = False
language= 'zh_CN'

然后编译的就会取翻译中文的html

处理po文件

下一步处理po文件,通过python处理

安装软件

1
pip-3 install polib

po文件的完整路径

1
ll /root/ceph/ceph12/doc/locales/zh_CN/LC_MESSAGES/

获取po文件的完整列表

polib的使用方法

这里用翻译po文件的代码举例

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
#! /usr/bin/python3
# -* coding:UTF-8 -*-
import time
import sys
import polib
import sys

import add_space

sys.path.append('../')
from google_translate import translate_google

#translate_google.translate_text_with_glossary("mozha,hello world")

def translate_po(file_path):
po = polib.pofile(file_path)
for entry in po:
print("原始字符串:")
print(entry.msgid)
mystringa=entry.msgid
newmsg=translate_google.translate_text_with_glossary("%s" %(mystringa))
print("翻译后未处理的字符串:")
print(newmsg)
newmsg=add_space.add_string_space(newmsg)
entry.msgstr = newmsg
print("翻译后的字符串:")
print(entry.msgstr)
time.sleep(0.1)
po.save(file_path)

translate_po(sys.argv[1])

这里用的比较少,流程是读取po文件,拿到原始字符串,然后翻译,再回写po文件,再进行保存,就完成一个po文件的处理了

google 的translate的用法

在凭据里面的服务账号里面创建一个密钥用于访问翻译的api
保存下来是一个json的文件

设置环境变量

我的是

1
export GOOGLE_APPLICATION_CREDENTIALS="/root/ceph/ceph12/admin/translate/3-google-translate/zphj1987-translate-797fe0ff0849.json"
1
2
[root@lab101 google_translate]# cat /etc/bashrc |tail -n 1
export GOOGLE_APPLICATION_CREDENTIALS="/root/ceph/ceph12/admin/translate/google_translate/zphj1987-translate-797fe0ff0849.json"

可以写到bashrc文件里面,登录命令行就直接可以使用了

安装python的翻译库

我们使用的是高级版本的

构建自己的术语表,需要上传到google的存储上面,然后告诉google翻译,去存储上面拿最新的存储的术语的文件,然后处理好了以后,返回成功

安装存储
官网推荐的是如下

1
pip-3 install --upgrade google-cloud-storage

上面的版本有问题尝试用之前的版本

1
pip-3 install google-cloud-translate==2.0.2

官网的文档没有更新到最新,匹配的是上面的2版本的

上传代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@lab101 3-google-translate]# cat uoload-csv.py 
from google.cloud import storage

def upload_blob(bucket_name, source_file_name, destination_blob_name):
"""Uploads a file to the bucket."""
# bucket_name = "your-bucket-name"
# source_file_name = "local/path/to/file"
# destination_blob_name = "storage-object-name"

storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(destination_blob_name)

blob.upload_from_filename(source_file_name)

print(
"File {} uploaded to {}.".format(
source_file_name, destination_blob_name
)
)

upload_blob('mytranslate','./ceph-glo.csv', 'ceph-glo.csv')

上传好自己的词库,还要告诉Google 翻译进行更新,字库的处理需要写脚本去读取po文件,然后保留一些固定的格式

安装gloud

1
2
3
4
5
6
7
8
9
10
tee -a /etc/yum.repos.d/google-cloud-sdk.repo << EOM
[google-cloud-sdk]
name=Google Cloud SDK
baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOM
1
yum install google-cloud-sdk

设置一个request文件来指定需要更新到哪个词库文件,然后先删除再更新即可

翻译的代码

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
#! /usr/bin/python3
# -* coding:UTF-8 -*-
from google.cloud import translate_v3 as translate

def translate_text_with_glossary(
text="YOUR_TEXT_TO_TRANSLATE",
project_id="zphj1987-translate",
glossary_id="myceph-en-zh",
):
client = translate.TranslationServiceClient()
parent = client.location_path(project_id, "us-central1")
glossary = client.glossary_path(
project_id, "us-central1", glossary_id # The location of the glossary
)

glossary_config = translate.types.TranslateTextGlossaryConfig(
glossary=glossary)
response = client.translate_text(
contents=[text],
target_language_code="zh",
source_language_code="en",
parent=parent,
glossary_config=glossary_config,
)
for translation in response.glossary_translations:
print(u"{}".format(translation.translated_text))
translate_text_with_glossary("mozha,hello world")

可以去google 官网查询api的用法

词库的提取方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@lab101 glocsv]# cat get_po_link_single.py
#! /usr/bing/python3
#-*- coding:UTF-8 -*-

#这个是处理`xxxx`_链接的

import polib
import re
import sys

po = polib.pofile(sys.argv[1])
for entry in po:
ms_string=entry.msgid
for rst_link in re.findall(r"`(.*?)`_",ms_string):
if '`' in rst_link:
if rst_link.split('`')[-1] == "":
pass
else:
print("\"`"+rst_link.split('`')[-1]+"`_\""+","+"\"`"+rst_link.split('`')[-1]+"`_\"" )
elif rst_link == "":
pass
else:
print("\"`"+rst_link+"`_\""+","+"\"`"+rst_link+"`_\"")

上面是处理单个po文件的,可以做好po文件的list,然后脚本去处理

1
2
3
4
5
6
7
8
9
10
11
12
[root@lab101 glocsv]# cat get_po_link_single.sh
#! /bin/sh
rm -rf po_link.csv
for pofile in `cat polist-do`
do
echo $pofile
python3 get_po_link_single.py $pofile >> po_link.csv.tmp
done

cat po_link.csv.tmp|sort|uniq > po_link.csv
sed -i '1 s/^/\xef\xbb\xbf&/' po_link.csv
rm -rf po_link.csv.tmp

上面的是其中一个例子的情况

需要特殊的处理哪些情况

翻译回来的中文会有问题,需要处理一些情况,主要的代码如下:

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
[root@lab101 translate_po]# cat add_space.py 
#! /usr/bin/python3
# -* coding:UTF-8 -*-
import re

##处理双引号无空格的问题
# 处理 **xxxxx**
def add_string_space(mystring):
for rst_link in re.findall(r"\*\*(.*?)\*\*",mystring):
newstring="**"+rst_link+"**"
mystring=mystring.replace('%s' %(newstring),' %s ' %(newstring))

# 处理`xxxx`_
for rst_link in re.findall(r"`(.*?)`_",mystring):
# print(rst_link)
if '`' in rst_link:
if rst_link.split('`')[-1] == "":
pass
else:
newstring='`'+rst_link.split('`')[-1]+"`_"
mystring=mystring.replace('%s' %(newstring),' %s ' %(newstring))
elif rst_link == "":
pass
else:
newstring="`"+rst_link+"`_"
mystring=mystring.replace('%s' %(newstring),' %s ' %(newstring))
#print(mystring)

# 处理 :term:`xxx`
for rst_link in re.findall(r":term:`(.*?)`",mystring):
newstring=":term:`"+rst_link+"`"
mystring=mystring.replace('%s' %(newstring),' %s ' %(newstring))

# 处理``xxxx``
for rst_link in re.findall(r"``(.*?)``",mystring):
newstring="``"+rst_link+"``"
mystring=mystring.replace('%s' %(newstring),' %s ' %(newstring))
# 处理:doc:`xxxx`
for rst_link in re.findall(r":doc:`(.*?)`",mystring):
newstring=":doc:`"+rst_link+"`"
mystring=mystring.replace('%s' %(newstring),' %s ' %(newstring))

# 处理其它情况
mystring=mystring.replace('。','.')
mystring=mystring.replace(',',',')
mystring=mystring.replace('”','')
mystring=mystring.replace('“','')
mystring=mystring.replace('(','(')
mystring=mystring.replace(')',')')
mystring=mystring.replace('\'\'','')
mystring=mystring.replace('',':')
mystring=mystring.replace('_ _','_ ')
mystring=mystring.replace('的Ubuntu','Ubuntu')
mystring=mystring.replace('CentOS的','CentOS')
mystring=mystring.replace(':项:` ','')
mystring=mystring.replace('','. ')
mystring=mystring.replace('',':')
mystring=mystring.replace(',','')
mystring=mystring.replace('/ ``',' ``')
mystring=mystring.replace('Bug Tracker_',' Bug Tracker_ ')
mystring=mystring.replace('[email protected]',' [email protected] ')
mystring=mystring.replace('http://ceph.com/docs',' http://ceph.com/docs ')
mystring=mystring.replace('[email protected]',' [email protected] ')
mystring=mystring.replace('[email protected]',' [email protected] ')
mystring=mystring.replace('http://github.com',' http://github.com ')

mystring=mystring.lstrip()

return(mystring)


流程总结

第一次处理全局翻译

1
2
3
4
1、获得一个google cloud translate的api,能够通过api进行翻译,这个也可以尝试其它的api,能够给英文返回中文及即可
2、提取ceph doc的po文件,能够修改po文件来实现翻译
3、维护一个字库,通过分析po文件的内容,脚本提取自己需要保留的固定格式或者固定的翻译,处理好了以后,提交到google 翻译里面更新
4、用脚本处理翻译返回的结果,然后再保留到po文件里面去

需要更新的情况

1
2
3
1、更新字库
2、更新处理脚本
3、翻译更新po文件

基于以上就可以打造一个自动翻译文档的系统了,当然这个翻译本身是需要一个校对的过程,所以使用过程中应该是不断晚上后面说的部分,就是维护好字库,维护好更新处理脚本,这个打造好了以后,再来新的版本,直接进行翻译即可,而校对的过程可以边学习文档边处理

翻译的api高级功能一般都是需要收费的,这个通常来说通过人工一个个去翻译,肯定花费的时间功夫是超过了api处理的,并且来新版本是能够很快处理完成的

更详细的代码

更详细的代码存放地址:

1
https://github.com/zphj1987/translate-ceph-doc-2020

由于对账户的依赖性比较高,上面的文章只记录了相关的思路,和重要的处理点,具体的可以自己实现

变更记录

Why Who When
创建 武汉-运维-磨渣 2020-09-04