<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>fantasticfears (Erick Guan)</title>
    <link>https://ruby-china.org/fantasticfears</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>Discourse 团队能给你什么？有什么样的职业机会？怎么加入？</title>
      <description>&lt;p&gt;原文在这：&lt;a href="https://meta.discoursecn.org/t/topic/2081" rel="nofollow" target="_blank"&gt;https://meta.discoursecn.org/t/topic/2081&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Discourse 团队一直在寻找 Rails 和 Ember.js 的开发者。整个团队分布多个大洲，用线上系统远程工作。工资待遇应该至少在 $10000/月。Discourse 的特色在于用户交互和游戏化的特性。如果你想有这样的工作机会，你可以直接参与社区，提交 patch 和帮助用户，团队自然会优先考虑于你。&lt;/p&gt;

&lt;p&gt;这个过程不简单，你需要很懂英语、会合作还要知道技术栈上的方方面面，也特别有意思。当然你还要很能坚持。&lt;/p&gt;

&lt;p&gt;我在中文社区这做过的事情很多都是国际化和本地化。如果你不知道从哪里开始，这是一个你会最熟悉的点，比较好切入。
这个 &lt;a href="https://github.com/fantasticfears/discourse-chinese-localization-pack" rel="nofollow" target="_blank"&gt;https://github.com/fantasticfears/discourse-chinese-localization-pack&lt;/a&gt; 插件就是本地化的重点了。Discourse 现在还需要在 Unicode 用户名、支持多个 OAuth2 provider（比如你可以用微博、QQ 登录然后绑定到同一个账户）和搜索上做更多改进。还有备份到七牛、又拍或者 UCloud 等等。
极光特别需要和微信的集成，但是这必须要官方支持多个 OAuth2 provider 这样的功能才能做到。
中文用户体验差的原因一半在于网络基础设施和环境的问题。将来如果官方对国内市场有兴趣，团队肯定会优先青睐于你。&lt;/p&gt;

&lt;p&gt;当然你也可以从翻译开始，这会是一个了解系统的很好方式。&lt;/p&gt;

&lt;p&gt;如果你有疑问，欢迎你提问。&lt;/p&gt;</description>
      <author>fantasticfears</author>
      <pubDate>Wed, 23 Aug 2017 14:42:27 +0800</pubDate>
      <link>https://ruby-china.org/topics/33907</link>
      <guid>https://ruby-china.org/topics/33907</guid>
    </item>
    <item>
      <title>怎么打造一个 ICU (Unicode) 的包装库？</title>
      <description>&lt;p&gt;祝大家🐵🎉&lt;/p&gt;

&lt;p&gt;这篇文章大概介绍了下 Unicode 带来的一些问题、相关的库和 Ruby 的一些实现，最后是我对这个问题的 2 个疑问。&lt;/p&gt;

&lt;p&gt;&lt;em&gt;以下内容有较多英文，力图表达最准确的意思。Unicode 相关的中文翻译有一些陌生和奇异。&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="Unicode 带来的问题"&gt;Unicode 带来的问题&lt;/h2&gt;
&lt;p&gt;Ruby 有完整的 &lt;a href="https://en.wikipedia.org/wiki/Unicode" rel="nofollow" target="_blank" title=""&gt;Unicode&lt;/a&gt; 支持，但是几乎不提供与 Unicode 相关的功能。2.2 的标准库里才添加了 &lt;a href="http://ruby-doc.org/stdlib-2.2.0/libdoc/unicode_normalize/rdoc/UnicodeNormalize.html" rel="nofollow" target="_blank" title=""&gt;Normalize&lt;/a&gt;（把字符分解成 Unicode 的基础组成方式，有 4 种方法，最常见的是 nfc）相关的功能。作为 CJK 的主要用户之一，很多情况下，我们可能会使用中文作为用户名或者名字。这不可避免地会有排序（transliteration，&lt;code&gt;音译&lt;/code&gt;）和比较（confusables）的问题。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transliteration：这是 &lt;a href="http://cldr.unicode.org/index" rel="nofollow" target="_blank" title=""&gt;Unicode CLDR (Common Locale)&lt;/a&gt; 处理的一个主要问题。常见的用途是排序。&lt;a href="http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-transliterate" rel="nofollow" target="_blank" title=""&gt;&lt;code&gt;ActiveSupport::Inflector.transliterate&lt;/code&gt;&lt;/a&gt; 即是这个功能。不过中文进去，&lt;code&gt;?&lt;/code&gt; 问号出来。&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://unicode.org/reports/tr39" rel="nofollow" target="_blank" title=""&gt;Confusables&lt;/a&gt;：这个问题很早就出现在域名上，叫做 &lt;a href="https://en.wikipedia.org/wiki/IDN_homograph_attack" rel="nofollow" target="_blank" title=""&gt;IDN homograph attack&lt;/a&gt;，利用肉眼无法分辨的 Cyrillic（俄罗斯）字符 &lt;code&gt;с&lt;/code&gt; 等来替代英文字符 &lt;code&gt;c&lt;/code&gt;，所以之后浏览器会在某些情况下显示 &lt;code&gt;xxx-xxx.com&lt;/code&gt; 这样的 Punycode。中文也有这样的 Unicode，如 &lt;code&gt;㍯ → 23点&lt;/code&gt;、&lt;code&gt;勇 → 勇&lt;/code&gt;（Chrome 已经用 ICU 处理过这些字符了，所以你是可以搜索匹配到两个的）。同样的情况，在名字这些重要要件中，这也是应该避免的东西，比如 &lt;code&gt;@&lt;/code&gt; 自动补全功能可能会让用户对错误的人执行无法预期的操作。（利用 unf 做的&lt;a href="https://github.com/fantasticfears/tr39_confusables" rel="nofollow" target="_blank" title=""&gt;玩具库&lt;/a&gt;）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;以上问题都是 Unicode 的冰山一角，我们尽量做我们能做的。&lt;/p&gt;
&lt;h2 id="已经有的 Gem"&gt;已经有的 Gem&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/twitter/twitter-cldr-rb" rel="nofollow" target="_blank" title=""&gt;twitter-cldr&lt;/a&gt;：纯 Ruby，在 CLDR 上的实现相当完整。&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/knu/ruby-unf" rel="nofollow" target="_blank" title=""&gt;unf&lt;/a&gt;：只做 Normarlization，C 写的，很快。不过有了官方库之后就不怎么必要了。&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/brianmario/charlock_holmes" rel="nofollow" target="_blank" title=""&gt;charlock_holmes&lt;/a&gt;：从 ICU 那里带来了一些功能，速度还行。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其他 Gem 就几乎没有怎么更新了，比如：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://rubygems.org/gems/icu4r/versions/0.1.4.2006.05.29" rel="nofollow" target="_blank" title=""&gt;icu4r&lt;/a&gt;：06 年&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ICU"&gt;ICU&lt;/h2&gt;
&lt;p&gt;这叫要说到一个处理 Unicode 的集大成者 ICU 了。&lt;a href="http://site.icu-project.org/" rel="nofollow" target="_blank" title=""&gt;ICU&lt;/a&gt; 是 IBM 专门拿来解决 Unicode 问题的库，C/C++ 和 Java 两种，及其成熟，16+ 年历史了。有挺多语言都有&lt;a href="http://site.icu-project.org/related" rel="nofollow" target="_blank" title=""&gt;自制的包装库&lt;/a&gt;。除此之外，我还能想到 iOS 的 Foundation 里有很多字符相关的功能是用它支持的。&lt;/p&gt;

&lt;p&gt;确实有很多软件依赖于它，甚至系统上也很容易找到库文件，OS X 上就有 &lt;code&gt;/usr/lib/libicucore.A.dylib&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;但是只有 Perl 和 PHP 把 ICU 的支持放在标准库里。JRuby 很幸运地直接用 icu4r 就好了...&lt;em&gt;Swift&lt;/em&gt; 倒是对 Unicode 有一个很不错的语言级别的实现。&lt;/p&gt;
&lt;h3 id="Ruby Core 对于 String 的考虑"&gt;Ruby Core 对于 String 的考虑&lt;/h3&gt;
&lt;p&gt;因为是 ICU 的包装，所以这个包装会碰到很多关于 Ruby 底层实现的问题。Ruby 底层用 byte array (char *) 存储 String，字符串本身可以是任意字符（Unicode！）。但这个 byte array 是有不同编码的（UTF-8、UTF-16）。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bugs.ruby-lang.org/issues/2034#note-10" rel="nofollow" target="_blank" title=""&gt;在 Ruby 1.9 后对于 m17n 的办法是 CSI Model&lt;/a&gt;，所以 Ruby 的 String 对象有 encoding 的信息，可以任意转换 encoding，但是在各种情况下都可以作为 String 使用。这就意味着 &lt;code&gt;String#[]&lt;/code&gt; 得到的结果一定是一个单一的字符，不论编码。&lt;/p&gt;

&lt;p&gt;所以很明显地，这是和 UCS（Universal Coded Character Set，&lt;a href="https://zh.wikipedia.org/wiki/%E9%80%9A%E7%94%A8%E5%AD%97%E7%AC%A6%E9%9B%86" rel="nofollow" target="_blank" title=""&gt;通用字符集&lt;/a&gt;）分道扬镳的一种方式。使用 UCS 模型的语言的底层编码类型应该是 UTF-8、UTF-16 和 UTF-32。而大部分语言的实现字符串的方式是 UCS 而不是 CSI。&lt;/p&gt;

&lt;p&gt;只是 Ruby 内部实现默认使用了 UTF-8 作为编码方式。&lt;/p&gt;

&lt;p&gt;MRI Ruby 没有用 ICU 的原因是要考虑多平台兼容性。&lt;/p&gt;
&lt;h3 id="ICU 的内部实现"&gt;ICU 的内部实现&lt;/h3&gt;
&lt;p&gt;ICU 选定了 &lt;a href="http://userguide.icu-project.org/strings" rel="nofollow" target="_blank" title=""&gt;UChar(uint16_t)&lt;/a&gt; 作为它的内部字符串的实现，Unicode 叫这个叫&lt;a href="https://en.wikipedia.org/wiki/Plane_(Unicode)" rel="nofollow" target="_blank" title=""&gt;Plane 平面&lt;/a&gt;。在这个级别上是没有大小端序的问题的。Unicode 字符是可以用 2^22 的点集表示的，所以一个 Unicode code point 是可以用 1、2 个（2 个的叫 surrogates，极少出现的情况）UChar 表示。UChar byte array 不一定是良好的 UTF-16 编码就是因为 surrogate 了。&lt;/p&gt;

&lt;p&gt;少部分的功能是有直接的 UTF-8 和 UTF-32 支持的。ICU 也支持 UTF-8 字符串到 UChar byte array 的相互转换。&lt;/p&gt;
&lt;h3 id="Ruby 能做到的"&gt;Ruby 能做到的&lt;/h3&gt;
&lt;p&gt;作为一个包装库，重要工作之一是把 Ruby String byte array 和 UChar byte array 对接起来。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MRI C 这个等级上可以得到 UTF-8 表示的 byte arrays，这个已经可以接上 ICU 的转换函数了。转换回来也不算困难。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;String#unpack(U*)&lt;/code&gt; 转换到的是 Unicode Code Point，这可以转换到 UTF-32。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;那么就可以开始考虑如何实现这个包装库了。&lt;/p&gt;
&lt;h2 id="包装库的目标和选择"&gt;包装库的目标和选择&lt;/h2&gt;
&lt;p&gt;目标：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;简单但易于扩展。ICU 是个极其庞大的库，应该尽量降低维护一个包装库的成本，没有人用的功能就留着。&lt;/li&gt;
&lt;li&gt;不造大轮子。ICU 的成熟度足够高，再用 Ruby 重写，实在过于复杂了。ICU 也把 Unicode 定义的数据很好地打包了。&lt;/li&gt;
&lt;li&gt;优秀的性能。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;那么不外乎选择：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C extension。这就是 icu4r 做的，问题在于很麻烦，相关的函数太多，包装是件很复杂的事情。有别的选择的话，我不太倾向于这个做法。&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ffi/ffi" rel="nofollow" target="_blank" title=""&gt;FFI&lt;/a&gt;。&lt;a href="https://github.com/fantasticfears/ffi-icu" rel="nofollow" target="_blank" title=""&gt;ffi-icu&lt;/a&gt; 是我从 jarib 那顺过来的一个 Gem。性能不错，用 Ruby 写起来还算轻松。这里最严重的问题在于 &lt;a href="https://github.com/fantasticfears/ffi-icu/blob/master/lib/ffi-icu/uchar.rb" rel="nofollow" target="_blank" title=""&gt;UChar 没有很好的实现，碰到 surrogates 就麻烦了&lt;/a&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="FFI"&gt;FFI&lt;/h3&gt;
&lt;p&gt;FFI 包装了 libffi，虽然说 libffi 都有好几年没更新了，但是这是一个很简单的创建包装库的办法。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;似乎没有什么重要的 gem 依赖于 ffi，这是个大问题么？rb-inotify 那个算是 development 使用的 gem 吧。&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/fantasticfears/ffi-icu/blob/uchar/lib/ffi-icu/uchar_pointer.rb" rel="nofollow" target="_blank" title=""&gt;操作 C API 转换到 UChar 的时候，已经转换回 Ruby 的 String 的时候&lt;/a&gt;，没有一个比较好的操作 FFI 的指针的办法。许多尝试都达不到正确地把 UChar 写回至 Ruby String。&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>fantasticfears</author>
      <pubDate>Fri, 12 Feb 2016 07:35:37 +0800</pubDate>
      <link>https://ruby-china.org/topics/28971</link>
      <guid>https://ruby-china.org/topics/28971</guid>
    </item>
    <item>
      <title>Discourse 即将 1.0.0，简单写了一篇中文安装指南。自己感觉翻译得还不够好。因为 postgresql 所以搜索问题很麻烦</title>
      <description>&lt;p&gt;原文持续更新：
&lt;a href="https://algalon.net/2014/04/discourse-%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97/" rel="nofollow" target="_blank"&gt;https://algalon.net/2014/04/discourse-%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97/&lt;/a&gt;
简书地址： &lt;a href="http://jianshu.io/p/269a448dc5ed" rel="nofollow" target="_blank"&gt;http://jianshu.io/p/269a448dc5ed&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;从刚开始开发到现在都 2014 年了，Discourse 很快就要发布 1.0.0 版了。欢迎尝鲜。&lt;/p&gt;

&lt;p&gt;elasticsearch-rails 用起来好像毫无痛感嘛...不知道替换掉 postgresql 的搜索不知道会出什么问题。&lt;/p&gt;</description>
      <author>fantasticfears</author>
      <pubDate>Sat, 19 Apr 2014 12:31:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/18708</link>
      <guid>https://ruby-china.org/topics/18708</guid>
    </item>
  </channel>
</rss>
