文档翻译方案
Closed this issue · 7 comments
目前Julia的源码采用Documenter.jl收集文档. 这个issue用来讨论怎么将中文文档加入到原生的代码里.
方案1请参看 JuliaCN/juliacn 这个repo
缺点是这个方案对REPL会build出一个新的binary.
方案2 修改Docs
这个module, 让Multi Docs能筛选语言标签(或者另外开发一个package用来支持i18n的语言标签筛选) 这个工程量可能比方案1大
EDIT:
In fact, @doc
is enough, it's simply: eval(Base.Math, quote @doc "aaaaa" sin(x) end)
. 😅
tl;dr
Documenter | REPL | Juno Documentation | |
---|---|---|---|
@doc (submodule) |
✅ | ❌ | ❌ |
DocStr (submodule) |
✅ | ✅ | ✅ |
@doc (main) |
✅ | ❌ | ❌ |
DocStr (main) |
❌ | ❌ | ✅ |
今晚试了一下,只用当前Docs
的API也可以覆盖原文档。
用@doc
覆盖
using Documenter
@doc "aaa" Base.Iterators.product
makedocs(format = :html, sitename = "test", pages = Any["Index" => "index.md"])
Documenter只生成aaa
,可以正确覆盖原文档,但REPL里只能增量添加,没有覆盖:
help?> Iterators.product
product(iters...)
Returns an iterator over the product of several iterators. Each generated element is a tuple
whose ith element comes from the ith argument iterator. The first iterator changes the fastest.
Example:
Example
≡≡≡≡≡≡≡≡≡
julia> collect(Iterators.product(1:2,3:5))
2×3 Array{Tuple{Int64,Int64},2}:
(1, 3) (1, 4) (1, 5)
(2, 3) (2, 4) (2, 5)
aaa
并且在Juno的Documentation里搜索product也会出来两个结果。
直接改DocStr
using Base.Docs: Binding, meta, MultiDoc
md = get!(meta(Base.Iterators), Binding(Base.Iterators, :product), MultiDoc())
md.docs[md.order[]].text = Core.svec("bbbbbb")
help?> Iterators.product
bbbbbb
在Documenter,REPL以及Juno的Documentation里均可以正确覆盖,但只适用于submodule中的函数,对于sin
函数无效:
using Base.Docs: Binding, meta, MultiDoc
md = get!(meta(Base.Math), Binding(Base.Math, :sin), MultiDoc())
md.docs[md.order[]].text = Core.svec("ssssssss")
help?> sin
search: sin sinh sind sinc sinpi asin using isinf asinh asind isinteger isinteractive sign signif
sin(x)
Compute sine of x, where x is in radians.
help?> Base.Math.sin
sin(x)
Compute sine of x, where x is in radians.
Documenter生成的和REPL显示的还是原来的文档,只有在Juno的Documentation里搜索的结果是覆盖的。最终的结果应该跟文档显示的实现方式有关,所以文档的html发布和REPL显示这两个功能还是分开考虑比较好?
我试验了一下, 大致理解了Docs是怎么存的了.
首先是meta
这个函数, 用来获取某个module下的Binding
=> MultiDoc
的一个Dict.
using Base.Docs: Binding, meta
doclist = meta(Base.Math) # 这里获得了Base.Math这个module下面所有的文档
接下来去这个Dict
里找sin
函数对应的MultiDoc
然后修改它.
sindoc = doclist[Binding(Base, :sin)]
然后我们看一下sindoc
的成员, 有两个
sindoc.docs
sindoc.order
docs
里面是一个ObjectIdDict
对象, 里面存储的是一个sig
(sig作为函数前面一般就是说一个用Tuple{A, B, ...}这样存下来的函数变量的类型的Tuple
类型)order
里面是函数的(被标记了文档的, 比如sin
被标记的那个是Any
类型的输入) 签名的显示顺序
我们要修改文档需要覆盖docs
里的内容. 先取出其中一项(对sin
来说只有一项), 键值为对应函数签名, 这里是Tuple{Any}
sindoc_content = sindoc.docs[Tuple{Any}]
这是一个DocStr
对象, 这其中有三个成员: data
, object
, text
data
: 存储一些meta信息, 和我们无关object
: 这里存储的应该是使用Markdown.parse
渲染后的一个Nullable
, 在外面套一个Nullable
的用意应该是让这个内容变得不可修改(也就是immutable), 所以我们需要自己重新产生一个这样的Nullable
text
: 这里是用Core.svec
存储的原始字符串, 暂时不知道存储的用意, 但是也需要修改
sindoc_content.object = Nullable(Markdown.parse("这是一个正弦函数"))
实际上对于REPL来说修改了这里在help mode里搜索出的sin
的文档就是中文的了.
@Roger-luo test
是原始文档,object
是parse之后的Markdown, 我之前只改了test
,而没有删除旧的Markdown, 所以没有成功, 直接把object
改成 nothing 就可以让它强制刷新:
julia> using Base.Docs: Binding, meta, MultiDoc
julia> md = get!(meta(Base.Math), Binding(Base.Math, :sin), MultiDoc())
Base.Docs.MultiDoc(Type[Tuple{Any}], ObjectIdDict(Pair{Any,Any}(Tuple{Any}, Base.Docs.DocStr(svec(" sin(x)\n\nCompute sine of `x`, where `x` is in radians.\n"), #NULL, Dict{Symbol,Any}(Pair{Symbol,Any}(:typesig, Tuple{Any}),Pair{Symbol,Any}(:module, Base.Math),Pair{Symbol,Any}(:linenumber, 303),Pair{Symbol,Any}(:binding, Base.sin),Pair{Symbol,Any}(:path, "math.jl"))))))
julia> md.docs[md.order[]].text = Core.svec("bbbbbb")
svec("bbbbbb")
julia> md.docs[md.order[]].object = nothing
help?> sin
search: sin sinh sind sinc sinpi asin using isinf asinh asind isinteger isinteractive sign signif signed Signed signbit
bbbbbb
这样覆盖这个功能已经OK了,发布binary的方案1可以否了。
OK, 我明白了. 那我们就采用package吧. Package就用DocInject.jl
这个repo可以么. 反正还没有添加内容. 那么现在大致思路就是用上面这个方法在DocInject
这个包里提供一个替换文档的宏, 然后在另外一个package: JuliaCN.jl
里提供中文文档, 并利用宏来注入中文. 大家还有啥意见没
不过我目前实现了一下这个宏, 很短, 其实
这个issue我就先关掉了,讨论到JuliaCN.jl下面继续吧
👌