30/09/2018, 16:19

Vietnamese slug cho Discourse

Em cũng chiến đấu với Discourse gần đây. Có viết 1 cái improve nhỏ cho Discourse để hỗ trợ Vietnamese slug. Nhưng mà pull request hoài mà không chấp nhận. Admin hay anh em nào giúp em hoàn thành để pull request vào core Discourse luôn. Code hiện tại hoạt động rất tốt.

Code:
https://github.com/thangngoc89/discourse/blob/master/lib/slug.rb

Website của em : ask.hoidapyhoc.com

Các lỗi còn tồn tại: chỉ hỗ trợ unicode dựng sẵn (1 byte) , chưa chơi với unicode tổ hợp (2 byte).
(Không thể theo cách này được vì 2 byte)

Nguyễn Minh Dũng viết 18:35 ngày 30/09/2018

Nhưng mà pull request hoài mà không chấp nhận

Jeff không đồng ý với slug này đâu đâu. @thangngoc89 phải thay vào

 if ['zh_CN', 'ja'].include?(SiteSetting.default_locale)

thành

 if ['zh_CN', 'ja', 'vi'].include?(SiteSetting.default_locale)

Nếu stringex có 'vi'

Cái này là tuyệt đối không được.

#For Vietnamese slug 
vietnamese   = "àáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸĐêùà"
replacements = "aaaaaaaaaaaaaaaaaeeeeeeeeeeeiiiiiooooooooooooooooouuuuuuuuuuuyyyyydAAAAAAAAAAAAAAAAAEEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOOOUUUUUUUUUUUYYYYYDeua"
string = string.tr(vietnamese, replacements)
#End Vietnamese slug
Lập Trình Sư viết 18:32 ngày 30/09/2018

cái này không phải là chức năng trong core nên reject là hoàn toàn dễ hiểu mà.

bạn phát triển riêng thành module plugin là được

thêm cả code style của bạn hardcode hơi quá, nhét cả text unicode vô trong string nữa là không được.

thiếu cả không có tests suite.

Nguyễn Minh Dũng viết 18:30 ngày 30/09/2018

Ngày trước Jeff không đồng ý, nhưng sau này thì họ đồng ý slug cho các ngôn ngữ khác tiếng anh.

Nhưng theo post của @thangngoc89 trên meta.discourse.org thì em nghĩ là có giải pháp. Với điều kiện mình khai báo cho stringex

Khoa Nguyen viết 18:28 ngày 30/09/2018

Do em không có rành về Ruby (chỉ nghiên cứu khi đến với Discourse) nên không rõ nữa.
@ltd anh có thể tiếp tục nghiên cứu không nhỉ?

Khoa Nguyen viết 18:31 ngày 30/09/2018

@laptrinhio trong php mình có contribute vào cái Slugify. Bây giờ làm project nào thì chỉ cần require nó là được. Ruby thì mình mù tịt

Nguyễn Minh Dũng viết 18:20 ngày 30/09/2018

Cái stringex vi này có vẻ không ổn lắm:

github.com

thangngoc89/stringex/blob/7917085cee35f9a14b4782f48eb1a2d5cd0a73bf/locales/vi.yml

# NOTE: Some translation keys make use of matches from regular expressions
# to manipulate whitespace and order. Please consult the source code for
# Stringex::Localization::ConversionExpressions to see what those
# regular expressions look like if you need to manipulate the order
# differently than the usage below.
vi:
  stringex:
    characters:
      and: va
      at: tai
      divide: divided by
      degrees: do
      dot: \1 cham \2
      ellipsis: dot dot dot
      equals: bang
      number: number
      percent: phan tram
      plus: cong
      slash: slash
      star: sao
This file has been truncated. show original

Đạt cũng không rành Ruby, nhưng mình phải giải quyết theo cách sử dụng stringex cho nó gọn code chứ không thể làm 2 cái mảng như thế này được

#For Vietnamese slug 
vietnamese   = "àáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸĐêùà"
replacements = "aaaaaaaaaaaaaaaaaeeeeeeeeeeeiiiiiooooooooooooooooouuuuuuuuuuuyyyyydAAAAAAAAAAAAAAAAAEEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOOOUUUUUUUUUUUYYYYYDeua"
string = string.tr(vietnamese, replacements)
#End Vietnamese slug

P/S: Đã star cái này lại và nghiên cứu

Khoa Nguyen viết 18:24 ngày 30/09/2018

@ltd cái Stringex đúng là rất không ổn.
Ngó phát qua php thì nó sẽ ra thế này

github.com

cocur/slugify/blob/master/src/Slugify.php#L444-534

  1. <?php
  2. /**
  3. * This file is part of cocur/slugify.
  4. *
  5. * (c) Florian Eckerstorfer <florian@eckerstorfer.co>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Cocur\Slugify;
  11. use Cocur\Slugify\RuleProvider\DefaultRuleProvider;
  12. use Cocur\Slugify\RuleProvider\RuleProviderInterface;
  13. /**
  14. * Slugify
  15. *
  16. * @package Cocur\Slugify
  17. * @author Florian Eckerstorfer <florian@eckerstorfer.co>
  18. * @author Ivo Bathke <ivo.bathke@gmail.com>
  19. * @author Marchenko Alexandr
  20. * @copyright 2012-2015 Florian Eckerstorfer
  21. * @license http://www.opensource.org/licenses/MIT The MIT License
  22. */
  23. class Slugify implements SlugifyInterface
  24. {
  25. const LOWERCASE_NUMBERS_DASHES = '/([^A-Za-z0-9]|-)+/';
  26. /**
  27. * @var array<string,string>
  28. */
  29. protected $rules = [];
  30. /**
  31. * @var RuleProviderInterface
  32. */
  33. protected $provider;
  34. /**
  35. * @var array<string,mixed>
  36. */
  37. protected $options = [
  38. 'regexp' => self::LOWERCASE_NUMBERS_DASHES,
  39. 'separator' => '-',
  40. 'lowercase' => true,
  41. 'trim' => true,
  42. 'strip_tags' => false,
  43. 'rulesets' => [
  44. 'default',
  45. // Languages are preferred if they appear later, list is ordered by number of
  46. // websites in that language
  47. // https://en.wikipedia.org/wiki/Languages_used_on_the_Internet#Content_languages_for_websites
  48. 'azerbaijani',
  49. 'burmese',
  50. 'hindi',
  51. 'georgian',
  52. 'norwegian',
  53. 'vietnamese',
  54. 'ukrainian',
  55. 'latvian',
  56. 'finnish',
  57. 'greek',
  58. 'czech',
  59. 'arabic',
  60. 'turkish',
  61. 'polish',
  62. 'german',
  63. 'russian',
  64. 'romanian'
  65. ],
  66. ];
  67. /**
  68. * @param array $options
  69. * @param RuleProviderInterface $provider
  70. */
  71. public function __construct(array $options = [], RuleProviderInterface $provider = null)
  72. {
  73. $this->options = array_merge($this->options, $options);
  74. $this->provider = $provider ? $provider : new DefaultRuleProvider();
  75. foreach ($this->options['rulesets'] as $ruleSet) {
  76. $this->activateRuleSet($ruleSet);
  77. }
  78. }
  79. /**
  80. * Returns the slug-version of the string.
  81. *
  82. * @param string $string String to slugify
  83. * @param string|array|null $options Options
  84. *
  85. * @return string Slugified version of the string
  86. */
  87. public function slugify($string, $options = null)
  88. {
  89. // BC: the second argument used to be the separator
  90. if (is_string($options)) {
  91. $separator = $options;
  92. $options = [];
  93. $options['separator'] = $separator;
  94. }
  95. $options = array_merge($this->options, (array) $options);
  96. // Add a custom ruleset without touching the default rules
  97. if (isset($options['ruleset'])) {
  98. $rules = array_merge($this->rules, $this->provider->getRules($options['ruleset']));
  99. } else {
  100. $rules = $this->rules;
  101. }
  102. $string = ($options['strip_tags'])
  103. ? strip_tags($string)
  104. : $string;
  105. $string = strtr($string, $rules);
  106. unset($rules);
  107. if ($options['lowercase']) {
  108. $string = mb_strtolower($string);
  109. }
  110. $string = preg_replace($options['regexp'], $options['separator'], $string);
  111. return ($options['trim'])
  112. ? trim($string, $options['separator'])
  113. : $string;
  114. }
  115. /**
  116. * Adds a custom rule to Slugify.
  117. *
  118. * @param string $character Character
  119. * @param string $replacement Replacement character
  120. *
  121. * @return Slugify
  122. */
  123. public function addRule($character, $replacement)
  124. {
  125. $this->rules[$character] = $replacement;
  126. return $this;
  127. }
  128. /**
  129. * Adds multiple rules to Slugify.
  130. *
  131. * @param array <string,string> $rules
  132. *
  133. * @return Slugify
  134. */
  135. public function addRules(array $rules)
  136. {
  137. foreach ($rules as $character => $replacement) {
  138. $this->addRule($character, $replacement);
  139. }
  140. return $this;
  141. }
  142. /**
  143. * @param string $ruleSet
  144. *
  145. * @return Slugify
  146. */
  147. public function activateRuleSet($ruleSet)
  148. {
  149. return $this->addRules($this->provider->getRules($ruleSet));
  150. }
  151. /**
  152. * Static method to create new instance of {@see Slugify}.
  153. *
  154. * @param array <string,mixed> $options
  155. *
  156. * @return Slugify
  157. */
  158. public static function create(array $options = [])
  159. {
  160. return new static($options);
  161. }
  162. }
This file has been truncated. show original

Nguyễn Minh Dũng viết 18:21 ngày 30/09/2018

cái Stringex đúng là rất không ổn.

Không, @thangngoc89 hiểu sai vấn đề rồi, cách họ translate vẫn rất ổn.

github.com

rsl/stringex/blob/39866d8235b757dcbcd80761f2150a799f8aa020/locales/pl.yml#L71-L88

  1. Ą: A
  2. Ć: C
  3. Ę: E
  4. Ł: L
  5. Ń: N
  6. Ó: O
  7. Ś: S
  8. Ź: Z
  9. Ż: Z
  10. ą: a
  11. ć: c
  12. ę: e
  13. ł: l
  14. ń: n
  15. ó: o
  16. ś: s
  17. ź: z
  18. ż: z

Trước hết mình phải pull request cho stringex vi trước, Tuy nhiên cái commit cho stringex vi này chưa được ổn

github.com

thangngoc89/stringex/blob/7917085cee35f9a14b4782f48eb1a2d5cd0a73bf/locales/vi.yml

# NOTE: Some translation keys make use of matches from regular expressions
# to manipulate whitespace and order. Please consult the source code for
# Stringex::Localization::ConversionExpressions to see what those
# regular expressions look like if you need to manipulate the order
# differently than the usage below.
vi:
  stringex:
    characters:
      and: va
      at: tai
      divide: divided by
      degrees: do
      dot: \1 cham \2
      ellipsis: dot dot dot
      equals: bang
      number: number
      percent: phan tram
      plus: cong
      slash: slash
      star: sao
This file has been truncated. show original

Và mình thiếu test cho cái stringex vi này

hey looks good. do you mind writing a test file for this? you can find examples in the test/unit/localization directory. need to have something to test against regressions for this. thanks.

Khoa Nguyen viết 18:32 ngày 30/09/2018

@ltd vấn đề là nằm ở chỗ default locale của Discourse. Mình không thể setting Vietnamese lên làm mặc định được :
https://www.transifex.com/projects/p/discourse-org/language/vi_VN/

Công việc translate mới được 36% (thời gian gần đây chỉ có mình làm việc translate này)

Test file thì gần như Khoa không biết làm (Ruby noob)

Nguyễn Minh Dũng viết 18:30 ngày 30/09/2018

Có hai lý do mà Đạt không làm cái này bởi vì

  • Đạt không muốn dịch sang tiếng Việt
  • Làm cái này cần đam mê

Về cái slug thì trước đây Đạt cũng nghĩ tới, có thể sẽ làm cái slug này ở local thôi, không nhất thiết phải đưa vào core.

Khoa Nguyen viết 18:35 ngày 30/09/2018

Okie. Đạt. Hy vọng là sẽ có được một giải pháp slug nhẹ nhàng, phù hợp cho Discourse.

Nguyễn Minh Dũng viết 18:21 ngày 30/09/2018

@thangngoc89, cái code đầu tiên bạn đưa ra ở trên của bạn cũng có thể apply cho DC local được rồi đấy, không nhất thiết phải PR để đưa vào core.

#For Vietnamese slug 
vietnamese   = "àáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸĐêùà"
replacements = "aaaaaaaaaaaaaaaaaeeeeeeeeeeeiiiiiooooooooooooooooouuuuuuuuuuuyyyyydAAAAAAAAAAAAAAAAAEEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOOOUUUUUUUUUUUYYYYYDeua"
string = string.tr(vietnamese, replacements)
#End Vietnamese slug

còn nếu muốn vào core thì phải làm như post trên:

Trước hết mình phải pull request cho stringex vi trước, Tuy nhiên cái commit cho stringex vi này chưa được ổn

Khoa Nguyen viết 18:31 ngày 30/09/2018

Okie @ltd mình đang áp dụng nó cho local mà.

Khoa Nguyen viết 18:35 ngày 30/09/2018

@ltd Không có gì mới, chỉ gom nó vào 1 plugin thôi

GitHub

thangngoc89/discourse-vietnamese-slug

Add Vietnamese Slug to Discourse. Contribute to thangngoc89/discourse-vietnamese-slug development by creating an account on GitHub.

Nguyễn Minh Dũng viết 18:23 ngày 30/09/2018

Nice, Đạt sẽ install cái này vào, nếu có bug thì Đạt sẽ report

P/S: Đã install rồi nhé @thangngoc89, chạy rất tốt

Khoa Nguyen viết 18:20 ngày 30/09/2018

Còn 1 lỗi mà làm biếng chưa bao giờ làm đó là hỗ trợ unicode tổ hợp (combine unicode)

Ví dụ topic: Hỏi vui: Mọi người hay gọi hai ký tự này là gì: '/' '\'

Nguyễn Minh Dũng viết 18:35 ngày 30/09/2018

oh, unicode tổ hợp nó có ký tự khác hả? Vậy còn có unicode nào nữa không?

Khoa Nguyen viết 18:30 ngày 30/09/2018

Chỉ đơn giản là quăng 1 bộ kí tự unicode và là xong

Thành Phạm viết 18:31 ngày 30/09/2018

Cái topic kia bị thế có thể là do em dùng bàn phím swype trên android nên nó k giống bình thường

Nguyễn Minh Dũng viết 18:27 ngày 30/09/2018

Như @thangngoc89 nói thì unicode tổ hợp bị lỗi. Rất có thể swype cũng sử dụng unicode tổ hợp. Cái này fix cũng dễ thôi. Có điều lười

Để sang Sing mà thấy không có ai làm thì Đạt commit cho bộ unicode tổ hợp.

Bài liên quan
0